JDBC数据库连接应用浅析

针对设问!相关问题如下:

1.什么是JDBC

2.怎么建立数据库连接(掌握)

3.关于Statement在操作数据表中的作用(了解)

4.使用PreparedStatement的 好处?具体应用方法是?(掌握)使用预编译的原因?连接数据库、操作表的步骤?

实现数据表的INSERT/UPDATE/DELETE操作

使用ResultSet和ResultSetMetaData实现数据表的SELECT操作

向数据表中插入、读取大数据:BLOB字段

INSERT / UPDATE / DELETE ; SELECT

6.数据库事务的操作方式(了解)

7.数据库连接池(理解)

C3P0数据库连接池

DBCP数据库连接池

8.JDBUtils工具类的使用(掌握)

使用QueryRunner,实现UPDATE()和QUERY()方法

利用DbUtils编写DAO通用类

解:

·1.1基础:

JDBC(Java Database Connectivity)是一个独立于特定数据库管理系统、通用的SQL数据库存取和操作的公共接口(一组API);JDBC可以连接任何提供了JDBC驱动程序的数据库系统;

·1.2 JDBC体系结构:

JDBC接口(API)包括两个层次:

 面向应用的API:Java API,抽象接口,供应用程序开发人员使用(连接数据库,执行SQL语句,获得结果)。

 面向数据库的API:Java Driver API,供开发商开发数据库驱动程序用。

JDBC是sun公司提供一套用于数据库操作的接口,java程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。不同的实现的集合,即为不同数据库的驱动。————面向接口编程

API执行流程图:

·2 获取数据库的连接

  1. 实现数据库连接的前提:a.加载与注册JDBC驱动;b.数据库 url;c.user 、password
  2. Driver接口:

Oracle的驱动:oracle.jdbc.driver.OracleDriver

mySql的驱动: com.mysql.jdbc.Driver

a. 加载与注册JDBC驱动分为两种方式:

方式一:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动名的类Class.forName(com.mysql.jdbc.Driver);

方式二:DriverManager 类是驱动程序管理器类,负责管理驱动程序

DriverManager.registerDriver(com.mysql.jdbc.Driver);

通常不用显式调用 DriverManager 类的 registerDriver() 方法来注册驱动程序类的实例,因为 Driver 接口的驱动程序类都包含了静态代码块,在这个静态代码块中,会调用 DriverManager.registerDriver() 方法来注册自身的一个实例

b.url的标准构成及对应数据库的使用形式:

·对于 Oracle 数据库连接,采用如下形式:

jdbc:oracle:thin:@localhost:1521:atguigu

·对于 SQLServer 数据库连接,采用如下形式:

jdbc:microsoft:sqlserver//localhost:1433; DatabaseName=sid

·对于 MYSQL 数据库连接,采用如下形式:   

jdbc:mysql://localhost:3306/atguigu

c. User,password可以用“属性名=属性值”方式告诉数据库;

·2.2 建立连接(Connection)

分为两类共5中方式:

A类:使用驱动Driver对象建立连接

a.连接方式一: 创建驱动对象driver,与数据源地址url和账号、密码进行校验、连接--配置文件对象

a.连接方式一: 创建驱动对象driver,与数据源地址url和账号、密码进行校验、连接--配置文件对象
@Test
	public void test() throws Exception {
		//1.获取驱动
		Driver driver  = new  com.mysql.jdbc.Driver();
		//2.数据库连接的url
		String url = "jdbc:mysql://localhost:3306/test";
		//3.用配置流设置数据库的账户和密码
		Properties info = new Properties();
		info.setProperty("user", "root");
		info.setProperty("password", "root");
		//4.连接数据库
		Connection connection = driver.connect(url,info);
		
		System.out.println(connection);
	}

b.连接方式二:通过反射获取驱动Driver对象driver(要向下转型)--配置文件对象
/*
	 * 连接方式二:通过反射获取驱动Driver对象driver(要向下转型)--配置文件对象
	 * 体会面向接口的编程思想
	 */
	
	@Test
	public void test2() throws Exception {
		//1.用驱动的全类名获取运行时类,创建Object类对象,获取驱动对象
		Class clazz = Class.forName("com.mysql.jdbc.Driver");
		Object object = clazz.newInstance();
		Driver driver = (Driver)object;
		//2.创建url链接
		String url = "jdbc:mysql://localhost:3306/test";
		//3.创建配置文件设置登陆账户与密码
		Properties info = new Properties();
		info.getProperty("user","root");
		info.getProperty("password","root");
		
		//4.链接数据库
		Connection connection = driver.connect(url,info);
		System.out.println(connection);
		
	}

B类:使用DriverMananger两个操作

 * 1.注册驱动

 * 2.获取连接

c.连接方式三:通过DriverMananger获取数据库的连接
@Test
	public void test3() throws Exception {
		//1.创建运行时类,获取驱动对象
		Class clazz = Class.forName("com.mysql.jdbc.Driver");
		Object object = clazz.newInstance();
		Driver driver =(Driver)object;
		
		//2.创建url数据源
		String url ="jdbc:mysql://localhost:3306/test";
		
		String user = "root";
		String password = "root";
		//3.注册驱动
		DriverManager.registerDriver(driver);
		
		//4.通过注册器 链接数据库
		Connection connection = DriverManager.getConnection(url, user,password);
		
		System.out.println(connection);
		
	}
d.连接方式四:mysql驱动默认会进行驱动的注册
@Test
	public void test4() throws Exception {
		
		//1.创建驱动的运行时类
		Class clazz =Class.forName("com.mysql.jdbc.Driver");
		//2.创建数据库账号、密码、url2.创建数据库账号、密码、url源源
		String url = "jdbc:mysql://localhost:3306/test";
		String user = "root";
		String password = "root";
		/*
		 * mysql可以不用注册,其它的数据库必须进行注册
		 * 这一步不要省。
		 */
		
		//链接数据库
		Connection connection =DriverManager.getConnection(url,user,password);
		
		System.out.println(connection);		
	}
e.方式五:使用配置文件获取数据库的连接(配置文件中存放user、password、url、driver)
@Test
	public void test5() throws Exception {
		//1.从配置文件读取数据
		InputStream iStream = this.getClass().getClassLoader()
				.getResourceAsStream("sqlDriver.properties");
		//2.创建配置文件对象
		Properties ps = new Properties();
		//3.加载文件内容到配置文件对象中
		ps.load(iStream);
		//3.从配置文件对象获取账户、密码、url、driver
		String user= ps.getProperty("user");
		String password = ps.getProperty("password");
		String driverClass = ps.getProperty("driverClass");
		String url = ps.getProperty("url");
		
		//4.创建驱动对象
		Class  clazz =Class.forName(driverClass);
		Object object = clazz.newInstance();
		Driver driver = (Driver)object;
		
		//5.注册驱动
		DriverManager.registerDriver(driver);
		
		//6.链接驱动
		Connection connection = DriverManager.getConnection(url,user,password);
		System.out.println(connection);
	}
}

·3.Statement 接口的使用与弊端

a.在对数据库的数据进行增删改查之前要先进行预编译,也就是对数据进行调用,java.sql 包中有 3 个接口:StatementPrepredStatement、CallableStatement.

b.Statement会遭受SQL注入攻击,所以不建议使用,主要使用PreparedStatement(从Statement扩展而来)

SQL注入攻击:利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1') ,从而利用系统的 SQL 引擎完成恶意行为的做法

·4.1.PreparedStatement 的好处,及应用方法

好处:最大可能提高性能(DBServer会对预编译语句提供性能优化)、最大可能提高性能

预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。(重要

连接数据库、操作表的步骤

释放资源:ResultSet 、 Connection PerpareStatement

关于ResultSet的说明

ResultSet: 结果集. 封装了使用 JDBC 进行查询的结果.

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

ResultSet 返回的实际上就是一张数据表. 有一个指针指向数据表的第一条记录的前面.

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

当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值.

例如: getInt(1), getString("name")

 

获取ResultSet中结果集的API常用方法:

next() 方法移动到下一行

getString() 根据占位符可获取对应的字符串数据

getInt().....套用以上格式

·4.2.ResultSetMetaData 类:

结果集获取表结构(元数据):

ResultSetMetaData meta = rs.getMetaData();

元数据常用API:

getColumnName(int column):获取指定列的

名称

getColumnLabel(int column):获取指定列的别名

getColumnCount():返回当前 ResultSet 对象中的列数。

getColumnTypeName(int column):检索指定列的数据库特的类型名称

得到结果集后, 如何知道该结果集中有哪些列 ? 列名是什么 ---- 需要使用一个描述 ResultSet 的对象, 即 ResultSetMetaData

ResultSetMetaData:可以获取对应的 ResultSet 有多少列, 每一列的列名都是什么。

1.如何获取 ResultSetMetaData: 调用 ResultSet 的 getMetaData() 方法即可

2.获取 ResultSet 中有多少列:调用 ResultSetMetaData 的 getColumnCount() 方法

3.获取 ResultSet 每一列的列的别名是什么。getColumnLabel() 方法

·4.3实现数据表的INSERT/UPDATE/DELETE操作

封装连接数据库到方法中——JDBCUtils

·4.3.1 普通增删改

1.封装连接数据库到方法中

/*
	 * 通用的增删改
	 */
	public static int UID(String sql,Object ...objects) {
		
		//1.获取数据库的链接
		Connection connection=null;
		//2.预编译
		PreparedStatement ps=null;
		//4.执行sql语句
	    int executeUpdate=-1;
		try {
			connection = JDBCUtils.getConnection();
			ps = connection.prepareStatement(sql);
			//3.填充数据
			for (int i = 0; i < objects.length; i++) {// i 表示索引
				ps.setObject(i + 1, objects[i]);// i + 1表示的是第几个占位符
			}
			executeUpdate = ps.executeUpdate();
		} catch (Exception e) {
			
			e.printStackTrace();
		}finally {
			
			 //5.关闭资源
		    JDBCUtils.close(connection, ps);
		}	   
	    
	    return executeUpdate;
	}	   

/*
	 * 获取数据库的连接
	 */
	public static Connection getConnection() {
		// 数据库的连接
		Connection connection = null;
		InputStream is = null;
		try {
			is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties");
			Properties ps = new Properties();
			ps.load(is);
			String user = ps.getProperty("user");
			String password = ps.getProperty("password");
			String driverClass = ps.getProperty("driverClass");
			String url = ps.getProperty("url");

			// 创建Driver对象
			Class clazz = Class.forName(driverClass);
			Object obj = clazz.newInstance();
			Driver driver = (Driver) obj;
			// 注册驱动
			DriverManager.registerDriver(driver);
			connection = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return connection;
	}
	public static void close(Connection connection,PreparedStatement ps) {
				if(connection!=null) {
					try {
						connection.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					}
				if(ps!=null) {
					try {
						ps.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			}
		}
	public static void close(Connection connection,PreparedStatement ps,ResultSet rs) {
		close(connection, ps);
		
		if(rs !=null ) {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

2.调用连接数据库类,填充数据,执行,关闭资源(关源封装到方法中

public class CRUDTest {
	/*
	 * 向数据库中插入一条数据
	 */
	@Test
	public void insert()  {
		
		//1.链接数据库
		Connection connection=null;
		//3.预编译
		PreparedStatement ps=null;
		try {
			connection = JDBCUtils.getConnection();
			//2.创建SQL语句
			String sql = "INSERT INTO customers(NAME,EMAIL,birth)" + " VALUES(?,?,?);";
			ps = connection.prepareStatement(sql);
			//4.设置内容
			ps.setString(1, "少培");// 第一个参数:第几个问号 第二个参数:内容
			ps.setString(2, "[email protected]");
			Date date = new Date(new java.util.Date().getTime());// 获取一个sql下的Date
			ps.setDate(3, date);
			//5.执行sql语句
			ps.execute();
		} catch (Exception e) {
			// TODO: handle exception
		}finally {
		//6.关闭资源
		JDBCUtils.close(connection,ps);
		}
	}
	/*
	 * 删除一条件数
	 */
	@Test
	public void delete() {
		
		//1.获取数据库的链接
		Connection connection=null;
		//3.预编译
		PreparedStatement ps=null;
		try {
			connection = JDBCUtils.getConnection();
			//2.创建sql语句
			String sql = "DELETE FROM customers WHERE id = ?";
			ps = connection.prepareStatement(sql);
			//4.填充数据
			ps.setInt(1, 19);
			//5.执行sql语句
			int i = ps.executeUpdate();
			System.out.println(i + "条语句受到影响");
		} catch (Exception e) {
			// TODO: handle exception
		}
		//6.关闭资源
		JDBCUtils.close(connection, ps);
	}
	/*
	 * 修改一条件数
	 */
	@Test
	public void update () throws Exception {
		
		//1.获取数据库的链接
		Connection connection=null;
		
		//3.预编译
		PreparedStatement ps=null;
		
		try {
			connection = JDBCUtils.getConnection();
			//2.创建sql语句
			String sql = "UPDATE customers SET NAME = ? WHERE id =?";
			ps = connection.prepareStatement(sql);
			//4.填充数据
			ps.setString(1, "霍光");
			ps.setInt(2, 21);
			//5.执行sql语句
			int executeUpdate = ps.executeUpdate();
		} catch (Exception e) {
			// TODO: handle exception
		}finally {
		//6.关闭资源
		JDBCUtils.close(connection,ps);	
		}
	}
	
	
}
2.通用增删改
1.封装连接数据库到方法中,执行语句也封装到同一个类中的方法中
/*
	 * 通用的增删改
	 */
	public static int UID(String sql,Object ...objects) {
		
		//1.获取数据库的链接
		Connection connection=null;
		//2.预编译
		PreparedStatement ps=null;
		//4.执行sql语句
	    int executeUpdate=-1;
		try {
			connection = JDBCUtils.getConnection();
			ps = connection.prepareStatement(sql);
			//3.填充数据
			for (int i = 0; i < objects.length; i++) {// i 表示索引
				ps.setObject(i + 1, objects[i]);// i + 1表示的是第几个占位符
			}
			executeUpdate = ps.executeUpdate();
		} catch (Exception e) {
			
			e.printStackTrace();
		}finally {
			
			 //5.关闭资源
		    JDBCUtils.close(connection, ps);
		}
	   
	   
	    
	    return executeUpdate;
	}
	/*
	 * 获取数据库的连接
	 */
	public static Connection getConnection() {
		// 数据库的连接
		Connection connection = null;
		InputStream is = null;
		try {
			is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties");
			Properties ps = new Properties();
			ps.load(is);
			String user = ps.getProperty("user");
			String password = ps.getProperty("password");
			String driverClass = ps.getProperty("driverClass");
			String url = ps.getProperty("url");

			// 创建Driver对象
			Class clazz = Class.forName(driverClass);
			Object obj = clazz.newInstance();
			Driver driver = (Driver) obj;
			// 注册驱动
			DriverManager.registerDriver(driver);
			connection = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return connection;
	}
	public static void close(Connection connection,PreparedStatement ps) {
				if(connection!=null) {
					try {
						connection.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					}
				if(ps!=null) {
					try {
						ps.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			}
		}
	public static void close(Connection connection,PreparedStatement ps,ResultSet rs) {
		close(connection, ps);
		
		if(rs !=null ) {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

2.创建sql语句及Date数据,调用连接数据库方法并调用执行方法。
public class CRUDTest2 {
	/*
	 * 测试通用的增删改
	 */
	@Test
	public void insert() {
		//1.创建sql语句
		String sql = " INSERT INTO customers(NAME,email,birth) VALUES(?,?,?)";
		//2.获取日期数据
		Date date =new java.sql.Date(new java.util.Date().getTime());
		//3.调用通用方法,执行修改
		int uid = JDBCUtils.UID(sql, "王玄策","[email protected]",date);
		//4.返回结果int
		System.out.println(uid + "条语句收到影响");
	}
	
}

·4.3.2

数据库的查找

1.普通查找

从数据库中查找一条数据或多条数据

从数据库中查找一条数据或多条数据
public class CRUDTest3 {
	
	/*
	 * 从数据库中查找一条数据或多条数据
	 */
	@Test
	public void select() throws Exception {
		
		Customer customer = getCustomerById();
		System.out.println(customer);
		
		List <Customer> list = getCustomers();
		for (Customer customer2 : list) {
			System.out.println(customer2);
		}
		
	}	
	
	/*
	 * 查询多条数据
	 */
	 
	public List<Customer>getCustomers() throws Exception {
		//1.创建数据库连接
		Connection connection = JDBCUtils.getConnection();
		//2.创建sql语句
		String sql = "select * from customers";
		//3.预编译
		PreparedStatement ps = connection.prepareStatement(sql);
		//4.执行sql语句
		ResultSet rs  = ps.executeQuery();
		//5.创建用于保存数据的集合
		List<Customer> list = new ArrayList<>();
		//6.获取数据,并将其封装的集合中
		
		while(rs.next()) {
			int id = rs.getInt("id");
			String name = rs.getString("name");
			String email = rs.getString("email");
			Date date = rs.getDate("birth");
			
			Customer customer = new Customer(id,name,email,date);
			
			list.add(customer);
		
		}
		//7.关闭资源
		JDBCUtils.close(connection,ps,rs);		
		return list;		
		
	}
	/*	 
	 * 查询一条数据	 
	 */
	
	 public Customer getCustomerById() throws Exception {
		
		 //1.获取数据库的连接
		 Connection connection = JDBCUtils.getConnection();
		 //2.创建sql语句
		 String sql = "SELECT * FROM customers where id =?";
		 //3.预编译
		 PreparedStatement ps = connection.prepareStatement(sql);
		 //4.填充数据
		 ps.setInt(1, 20);
		 //5.执行sql语句
		 ResultSet rs  = ps.executeQuery();// 查找的结果都已经放到ResultSet中了
		 
		 Customer customer=null;
		 //6.从结果集中获取数据
		 if(rs.next()) {
			 
			 int id =rs.getInt("id");
			 String name = rs.getString("name");
			 String email = rs.getString("email");
			 Date birth = rs.getDate("birth");
			 
		  //7.封装数据到自定义类中
			 customer= new Customer(id,name,email,birth);
		  //8.输出结果
			 System.out.println(id + " " +name + " "+ email + " " +birth);
		 }
		 JDBCUtils.close(connection, ps,rs);
		 return customer;
	 }
}

	/*
	 * 获取数据库的连接
	 */
	public static Connection getConnection() {
		// 数据库的连接
		Connection connection = null;
		InputStream is = null;
		try {
			is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties");
			Properties ps = new Properties();
			ps.load(is);
			String user = ps.getProperty("user");
			String password = ps.getProperty("password");
			String driverClass = ps.getProperty("driverClass");
			String url = ps.getProperty("url");

			// 创建Driver对象
			Class clazz = Class.forName(driverClass);
			Object obj = clazz.newInstance();
			Driver driver = (Driver) obj;
			// 注册驱动
			DriverManager.registerDriver(driver);
			connection = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return connection;
	}
	public static void close(Connection connection,PreparedStatement ps) {
				if(connection!=null) {
					try {
						connection.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					}
				if(ps!=null) {
					try {
						ps.close();
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			}
		}
	public static void close(Connection connection,PreparedStatement ps,ResultSet rs) {
		close(connection, ps);
		
		if(rs !=null ) {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
}

2.通用查找

public class JDBCUtils2 {
	
	public static void main(String[] args) throws Exception {
		//创建sql语句
		String sql = "select id,name,email,birth  from customers where id=?";
		Customer customer = getObject(Customer.class, sql, 5);
		System.out.println(customer);
		
		sql = "select * from users where id=?";
		User object = getObject(User.class, sql, 1);
		System.out.println(object);
		
		sql = "select * from users";
		List <User> users = getObjects(User.class, sql);
		for (User user : users) {
			System.out.println(user);
		}
	}

	
	/*
	 * 通用的查找 (只一条数据)
	 * 
	 * Class<T> clazz : 运行时类的对象
	 */
	public static <T> T getObject(Class<T>clazz,String sql,Object ...objects) throws Exception {
		//1.获取数据库的连接
		Connection connection =JDBCUtils.getConnection();
		//2.预编译
		PreparedStatement ps = connection.prepareStatement(sql);
		//3.填充数据
		for(int i = 0;i<objects.length;i++) {
			ps.setObject(i+1, objects[i]);
		}
		//4.执行sql语句
		ResultSet rs = ps.executeQuery();
		//5.获取元数据
		ResultSetMetaData md = rs.getMetaData();
		//6.获取列的数量
		int columnCount = md.getColumnCount();
		//7.创建运行时类的对象
		T t =clazz.newInstance();
		//8.while循环获取每一条数据
		while(rs.next()) {//遍历每一条数据
			/*
			 * 第一个问题 : 如何获取到表的列数
			 * 第二个问题 : 需要知道类中的属性
			 * 第个问题 : 对象中属性的名字怎么来
			 */
			//9.for循环获取每一列的数据并封装到自定义对象的属性中
			for(int i =0;i<columnCount;i++) {
				//a.通过列的索引获取列明(如果别名获取的是别名
				String columnLabel=md.getColumnLabel(columnCount);
				//b.通过列名获取列中的数据
				Object value = rs.getObject(columnLabel);
				
				//封装
				//通过反射 - 给对象中的属性进行赋值
				//将表中的列名当作类中的属性名。如果列名和属性名不一样,可以通过别名的方式(别名 = 属性名
				//通过列名就获取到了类中的对应的属性
				Field declaredField = clazz.getDeclaredField(columnLabel);
				declaredField.setAccessible(true);
				/*
				 * 第一个参数 : 是给哪个对象进行赋值
				 * 第二个参数 : 属性值
				 */
				declaredField.set(t,value);				
			}						
		}
		//关闭资源
		JDBCUtils.close(connection,ps,rs);
		
		return t;
	}
	/*
	 * 通用的查找 (返回多条数据
	 * 
	 */
	public static <T> List<T> getObjects(Class<T>clazz,String sql,Object...objects) throws Exception{
		
		//1.获取数据库的连接
		Connection connection = JDBCUtils.getConnection();
		//2.预编译
		PreparedStatement ps = connection.prepareStatement(sql);
		//3.填充数据
		for(int i= 0;i<objects.length;i++) {
			ps.setObject(i+1, objects[i]);
		}
		//4.执行sql语句
		ResultSet rs = ps.executeQuery();
		//5.获取元数据
		ResultSetMetaData md = rs.getMetaData();
		//6.获取列数
		int colunmCount = md.getColumnCount();
		//7.创建一个集合用于接收数据
		List <T> list = new ArrayList<>();
		//8.while循环获取每一条数据
		while(rs.next()) {
			
			//a.创建对象
			T t = clazz.newInstance();
			//b.获取每一列的列名,并且通过列明获取数据
			for(int i=0;i<colunmCount;i++) {
				//获取列名
				String columnLabel = md.getColumnLabel(i+1);
				//获取列的数据
				Object value = rs.getObject(columnLabel);
				//封装
				//通过反射 - 给对象中的属性进行赋值
				//将表中的列名当作类中的属性名。如果列名和属性名不一样,可以通过别名的方式(别名 = 属性名
				//通过列名就获取到了类中的对应的属性
				Field declardField = clazz.getDeclaredField(columnLabel);
				declardField.setAccessible(true);
				/*
				 * 第一个参数 : 是给哪个对象进行赋值
				 * 第二个参数 : 属性值
				 */
				declardField.set(t, value);
			}
			//将对象放入集合中
			list.add(t);
		}
		//关闭资源
		JDBCUtils.close(connection, ps,rs);
		return list;
		
	}
	
}	

·4.3.3 向数据表中插入、读取大数据:BLOB字段

MySQL中,BLOB是一个二进制大型对象,是一个可以存储大量数据的容器,它能容纳不同大小的数据。

BLOB字段由两部分组成:数据(值)和指向数据的指针(定位器)。定位器被存放在列中,值被存放在LOB段中,LOB段是在数据库内部表的一部分。在写入Blob之前,必须获得指针(定位器)才能进行写入.

如何获得Blob的指针(定位器) :需要先插入一个empty的blob,这将创建一个blob的指针,然后再把这个empty的blob的指针查询出来,这样通过两步操作,就获得了blob的指针,可以真正的写入blob数据了

/*
 * 获取Blob类型的数据
 * 
 * 向Blob字段中插入数据
 */
public class BlobTest {

	
	@Test
	public void insert() throws Exception{
		
		Connection connection = JDBCUtils.getConnection();
		
		String sql = "insert into customers(photo) values(?)";
		
		PreparedStatement ps = connection.prepareStatement(sql);
		
		FileInputStream fis = new FileInputStream("123.jpg");
		
		ps.setBlob(1, fis);
		
		boolean execute = ps.execute();
		
		fis.close(); //关流
		
		JDBCUtils.close(connection, ps);
		
	}
	
//	/*
	从数据库读取数据,写到目录下
*/
	@Test
	public void select() throws Exception{
		
		Connection connection = JDBCUtils.getConnection();
		
		String sql = "select photo from customers where id = ?";
		
		PreparedStatement ps = connection.prepareStatement(sql);
		
		ps.setInt(8, 21);
		
		ResultSet rs = ps.executeQuery();
		
		if(rs.next()){
			
			Blob blob = rs.getBlob("photo");
			
			InputStream is = blob.getBinaryStream();
			
			FileOutputStream fos = new FileOutputStream("555.jpg");
			
			byte[] b = new byte[1024];
			int len = 0;
			while((len = is.read(b)) != -1){
				fos.write(b,0,len);
			}
			
			fos.close();
			is.close();
		}
		
		JDBCUtils.close(connection, ps,rs);
		
	}
}

·4.4 数据库事务

1.事务:一组逻辑操作单元,使数据从一种状态变换到另一种状态。

2.事务处理(事务操作):保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),那么这些修改就永久地保存下来;要么数据库管理系统将放弃所作的所有修改,整个事务回滚(rollback)到最初状态

3.为了让多个 SQL 语句作为一个事务执行:

调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务

在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务

在出现异常时,调用 rollback(); 方法回滚事务

若此时 Connection 没有被关闭, 则需要恢复其自动提交状态

 

4.事务的ACID(acid)属性

a. 原子性  

b. 一致性

c. 隔离性

d. 持久性、

代码:

package com.atguigu.java2;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.junit.Test;
import com.atguigu.java.JDBCUtils;
/*
 * 数据库事务
 */
public class Transaction {
	/*
	 * 需求 : AA 给 BB 转账
	 * 第一步:AA减去100
	 * 第二步 :BB加上100
	 * 
	 *  UPDATE user_table SET balance=balance - 100 WHERE USER='AA'

		UPDATE user_table SET balance=balance + 100 WHERE USER='BB'
	 * 
	 * 要完成都完成,要失败都失败。
	 * 
	 * 注意 :1.事务中多个sql语句必须使用同一个连接。
	 */
	@Test
	public void test(){
		String sql = " UPDATE user_table SET balance=? WHERE USER=?";
		
		Connection connection = JDBCUtils.getConnection();
		
		try {
			//设置不让自动提交
			connection.setAutoCommit(false);
			
			UID(connection,sql, 900, "AA");
			System.out.println(1 / 0);
			UID(connection,sql, 1100, "BB");
			
			connection.commit();
		} catch (Exception e) {
			//回滚
			try {
				connection.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			
		}finally{
			try {
				connection.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
	}
	
	/*
	 * 通用的增删改
	 */
	public  int UID(Connection connection,String sql,Object ...objects) {	
		// 2. 预编译
		PreparedStatement ps = null;
		// 4.执行sql语句
		int executeUpdate = -1;
		try {
			ps = connection.prepareStatement(sql);
			// 3.填充数据
			for (int i = 0; i < objects.length; i++) { // i 表示索引
				ps.setObject(i + 1, objects[i]); // i + 1表示的是第几个占位符
			}
			executeUpdate = ps.executeUpdate();	
		} catch (Exception e) {
			e.printStackTrace();
		}
		return executeUpdate;
	}
}

工具类:
package com.atguigu.java;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCUtils {
	/*
	 * 通用的增删改
	 */
	public static int UID(String sql,Object ...objects) {
		// 1. 获取数据库的连接
		Connection connection = null;
		// 2. 预编译
		PreparedStatement ps = null;
		// 4.执行sql语句
		int executeUpdate = -1;
		try {
			connection = JDBCUtils.getConnection();
			ps = connection.prepareStatement(sql);
			// 3.填充数据
			for (int i = 0; i < objects.length; i++) { // i 表示索引
				ps.setObject(i + 1, objects[i]); // i + 1表示的是第几个占位符
			}
			executeUpdate = ps.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			// 5.关闭资源
			JDBCUtils.close(connection, ps);
		}
		return executeUpdate;
	}

	/*
	 * 获取数据库的连接
	 */
	public static Connection getConnection() {
		// 数据库的连接
		Connection connection = null;
		InputStream is = null;
		try {
			is = JDBCUtils.class.getClassLoader().getResourceAsStream("sqlDriver.properties");
			Properties ps = new Properties();
			ps.load(is);
			String user = ps.getProperty("user");
			String password = ps.getProperty("password");
			String driverClass = ps.getProperty("driverClass");
			String url = ps.getProperty("url");

			// 创建Driver对象
			Class clazz = Class.forName(driverClass);
			Object obj = clazz.newInstance();
			Driver driver = (Driver) obj;
			// 注册驱动
			DriverManager.registerDriver(driver);
			connection = DriverManager.getConnection(url, user, password);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return connection;
	}

	public static void close(Connection connection, PreparedStatement ps) {
		if (connection != null) {
			try {
				connection.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

		if (ps != null) {
			try {
				ps.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	public static void close(Connection connection, PreparedStatement ps, ResultSet rs) {
		close(connection,ps);
		
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
	}
}

 

猜你喜欢

转载自blog.csdn.net/weixin_42405670/article/details/82468873