JDBC

JDBC

jdbc的目标是使java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统

 

Java应用程序——>JDBC API——>JDBC驱动程序——>数据库

 

Java.sql.Driver接口是所有JDBC驱动程序需要实现的接口。

》这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现

》在程序中不需要直接访问实现了Driver接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现

数据库厂商必须实现的接口,能从中获取数据库的连接

 

/**
 * JDBC URL
 * jdbc:mysql://localhost:3306/test
 *
 * 对于oracle数据库连接:
 * jdbc:oracle:thin:@localhost:1521:sid
 *
 * 对于SQLserver数据库连接:
 * jdbc:miscrosoft:sqlserver//localhost:1433;DatabaseName=sid
 *
 * 对于MYSQL数据库连接:
 * jdbc:mysql://localhost:3306/sid
 */

  

连接数据库的步骤:

1、注册驱动(只做一次)

2、建立连接(Connection)

3、创建执行SQL的语句(Statment)

4、执行语句

5、处理执行结果(ResultSet)

6、释放资源

 

DriverManager 是驱动的管理类

 

1)可以通过重载的getConnection()方法获取数据库连接,较为方便

 

2)可以同时管理多个驱动程序:若注册多个数据库连接,则调用getConnection()方法时传入的参数不同,即返回不同的数据库连接

		String driverClass = "oracle.jdbc.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:orcl";
		String user = "scott";
		String password = "123456";
		//加载数据库驱动程序(对应的Driver实现类中有注册驱动的静态代码块)
		//DriverManager.registerDriver((Driver) Class.forName(driverClass).newInstance());
		Class.forName(driverClass);
		Connection conn = DriverManager.getConnection(url, user, password);
		System.out.println(conn);

 

通过配置文件jdbc.properties获取数据库连接

String driverClass = "oracle.jdbc.OracleDriver";
		String url = "jdbc:oracle:thin:@localhost:1521:orcl";
		String user = "scott";
		String password = "123456";
		
		//读取配置文件信息
		InputStream is = getClass().getClassLoader().getResourceAsStream("jdbc.properties");
		Properties pro = new Properties();
		
		//将读取的配置文件信息传入pro
		pro.load(is);
		
		//根据值进行查询赋值
		driverClass = pro.getProperty("driverClass");
		url = pro.getProperty("url");
		user = pro.getProperty("user");
		password = pro.getProperty("password");
		
		//创建一个驱动对象   Class.forName() 加载数据库驱动
		Driver driver = (Driver) Class.forName(driverClass).newInstance();
		Properties info = new Properties();
		info.put("user",user);
		info.put("password",password);
		
		//通过driverManager的getConnection()方法获取连接
		Connection conn = DriverManager.getConnection(url, info);
		
		return conn;

  

 

 

*增、删、改用Statement.executeUpdate来完成,返回整数(匹配的记录数),这类操作相当简单。

*查询用Statement.executeQuery来完成,返回的是ResultSet对象,ResultSet中包含了查询的结果。

 

创建与数据库的连接的标准方式是在

DriverManager上调用方法getConnection().

 

statement(语句对象)

》executeUpdate(String sql):

执行SQL insert,update或delete语句,返回受影响的行的数目或零;返回值为int型

》executeQuery(String sql)

执行返回单个ResultSet的SQL语句;返回类型ResultSet

》execute(String sql)

执行可以返回多个结果的SQL语句。返回类型boolean,如果返回的是更新的数目,则返回false,如果返回ResultSet,则返回true。(不常用)

 

		//1.获取数据库连接
		Connection conn = getConnection();
		
		//2.准备插入的sql语句
		String sql = "insert into student values(3,'123','123')";

		//3.执行插入	
		//(1)获取操作与SQL语句的Statement对象
		Statement state = conn.createStatement();
		
		//(2)调用Statement对象的executeUpdate(sql)执行SQL语句进行插入
		int result = state.executeUpdate(sql);
		System.out.println(result);
		
		//4.关闭Statement对象
		state.close();
		
		//5.关闭连接
		conn.close();

 

PreparedStatement

* 使用PreparedStatement
* 1)why?
 ①使用statement需要进行拼写SQL语句。很辛苦,而且容易出错。

 ②可以有效地禁止SQL注入。

  ——SQL诸如是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入,数据中注入非法的SQL语句段

  ——对于Java而言,要规范SQL注入,只要用PreparedStatement取代Statement就可以了。

SQL注入

String username = "a' OR PASSWORD = ";
String password = "OR '1' = '1";

String sql = "SELECT * FROM USERS WHERE USERNAME = '" 
			+ username + "' AND "
			+ "PASSWORD = '" 
			+ password
			+ "'";
 }
select * from users where username = 'a' or password = 'and password = ' or '1' = '1'

 《3》PreparedStatement能最大可能提高性能

 


* 2)PreparedStatement:是Statement的子接口,可以传入带占位符的SQL语句,而且
* 提供了补充占位符变量的方法。
*
* 使用PreparedStatement
* ①创建PreparedStatement:
* String sql = "INSERT INTO STUDENT VALUES(?,?,?,?,?)"
* PreparedStatement ps = conn.prepareStatement(sql);
*
* ②调用PreparedStatement的setXxx(int index,Object val)设置占位符的值。
* index值从1开始
*
* 3执行SQL语句:executeQuery()或executeUpdate().注意:执行时不再需要传入SQL语句

 

	@Test
	public void test2(){
		Connection conn = null;
		PreparedStatement preparedStatement = null;
		
		try {
			conn = getConnection();
			String sql = "insert into examstudent values(?,?,?,?,?,?,?)";
			
			preparedStatement =  conn.prepareStatement(sql);
			
			preparedStatement.setInt(1,11);
			preparedStatement.setInt(2, 2);
			preparedStatement.setString(3, "43121223113");
			preparedStatement.setString(4,"1245523");
			preparedStatement.setString(5,"yhs");
			preparedStatement.setString(6,"dwd");
			preparedStatement.setInt(7,3);
			
			int re = preparedStatement.executeUpdate();
			if(re ==1){
				System.out.println("插入成功!!!");
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			release(preparedStatement, conn, null);
		}
	}

 

  

 

ResultSet

结果集读取数据的方法主要是getXXX(),他的参数可以使整数表示第几列(从1开始的),还可以是列名。

返回的是对应的XXX类型的值。如果对应那列时空值,XXX是对象的话返回XXX型的空值,如果XXX是数字类型,如Float等返回0,boolean返回false

 

结果集,封装了使用JDBC进行查询的结果

1.调用Statement对象的executeQuery(sql)可以得到结果集

2.ResultSet返回的实际上就是一张数据表,有一个指针指向数据表的第一行的前面

可以使用next()方法检测下一行是否有效,若有效该方式返回true,且指针下移。

相当于Iterator对象的hasNext()和next()方法的结合体

3.当指针对位到一行时,可以通过getXxx(index)或getXxx(columnName)

获取每一列的值,例如:getInt(1),getString("name")

4.ResultSet:当然也需要进行关闭

 

单条数据查询:

		Connection conn = getConnection();
		Statement state = conn.createStatement();
		
		String sql = "select * from student where id=1";
		ResultSet rs = state.executeQuery(sql);
		if(rs.next()){
			int id = rs.getInt(1);
			String name = rs.getString("name");
			String password = rs.getString("password");
			
			System.out.println(id);
			System.out.println(name);
			System.out.println(password);
		}
		
		conn.close();
		state.close();
		rs.close();

 

多条数据查询:

		Connection conn = getConnection();
		Statement state = conn.createStatement();
		
		String sql = "select * from student";
		ResultSet rs = state.executeQuery(sql);
		while(rs.next()){
			int id = rs.getInt(1);
			String name = rs.getString("name");
			String password = rs.getString("password");
			
			System.out.print(id + "  ");
			System.out.print(name + "  ");
			System.out.println(password);
		}
		
		conn.close();
		state.close();
		rs.close();

  

封装查询多个对象的方法:

ResultSetMetaData:(解决红色部分)接口

1)what:是描述ResultSet的元数据对象,即从中可以获取到结果集有多少列,列名是什么....

2) how:

<1>得到ResultSetMetaData  对象:调用ResultSet的getMetaData()方法

<2>ResultSetMetaData有哪些好用的方法

  >int getColumnCount(): SQL语句包含哪些列

  >String getColumnLabel(int column):获取指定的列的别名,其中索引从1开始。

获取结果集每一列的别名

for(int i=0;i<rsmd.getColumnCount();i++){

  String columnLabel = rsmd.getColumnLabel(i+1);

}

 

 

 

public <T> T testResultSetMetaData(Class<T> clazz,String sql,Object...args){
		Connection conn = null;
		PreparedStatement preparedstatement = null;
		ResultSet resultset = null;
		T entity = null;
		
		try {
			conn = getConnection();
			preparedstatement = conn.prepareStatement(sql);
			//对sql占位符进行赋值
			for(int i=0;i<args.length;i++){
				preparedstatement.setObject(i+1,args[i]);
			}
			resultset = preparedstatement.executeQuery();
			
			ResultSetMetaData metaData = resultset.getMetaData();
				
			Map<String,Object> map = new HashMap<String,Object>();
			while(resultset.next()){
				for(int i=0;i<metaData.getColumnCount();i++){
					String columnLabel = metaData.getColumnLabel(i+1);
					Object obj = resultset.getObject(i+1);
					map.put(columnLabel, obj);
					System.out.println(columnLabel + " " +obj);
				}
			}
			if(map.size()>0){
				entity = clazz.newInstance();
				
				//遍历Map对象,利用反射为Class对象对应的属性赋值
				for(Map.Entry<String, Object> entry : map.entrySet()){
					String fieldName = entry.getKey();
					Object value = entry.getValue();
					BeanUtil
				}
			}
			
		} catch (Exception e) {
			// TODO: handle exception
		}finally{
			release(preparedstatement, conn, resultset);
		}
		return null;
	}
	

  

 

posted @ 2019-04-20 10:55  鸿森  阅读(182)  评论(0编辑  收藏  举报