JavaWeb之JDBC(2.2):数据库事务、数据库连接池、DBUtils、DAO及其子类代码演示

本文主要是介绍JavaWeb之JDBC(2.2):数据库事务、数据库连接池、DBUtils、DAO及其子类代码演示,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写在前面:JDBCUtils类代码主要提供对MySQL数据库的连接、关闭功能,Customer和Order等bean类主要封装对应数据库相关属性并提供get、set、toString方法及构造器,具体代码请看前面的博文。

附上JDBCUTils类代码

package JavaWeb.JDBC.day3.util;import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;import javax.sql.DataSource;import JavaWeb.JDBC.day3.connection.DBCPTest;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.apache.commons.dbutils.DbUtils;import com.mchange.v2.c3p0.ComboPooledDataSource;/*** 提供数据库连接、关闭等操作的工具类*/
public class JDBCUtils {/*** 测试main方法* @param args* @throws SQLException*/public static void main(String[] args) throws SQLException {Connection conn = getC3P0Connection();System.out.println(conn);}// 关闭资源的操作public static void closeResource(Connection conn, Statement st, ResultSet rs) {try {DbUtils.close(conn);} catch (SQLException e) {e.printStackTrace();}try {DbUtils.close(st);} catch (SQLException e) {e.printStackTrace();}try {DbUtils.close(rs);} catch (SQLException e) {e.printStackTrace();}}// 关闭资源的操作public static void closeResource(Connection conn, Statement st) {if (conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}if (st != null) {try {st.close();} catch (SQLException e) {e.printStackTrace();}}}// 获取连接的操作public static Connection getConnection() throws Exception {// 1.加载配置文件Properties pros = new Properties();FileInputStream fis = new FileInputStream("D:\\Workspaces\\Java20190715\\TeacherProgram\\src\\jdbc.properties");pros.load(fis);// 2.获取连接所需的四个基本信息String driverClass = pros.getProperty("driverClass");String url = pros.getProperty("url");String user = pros.getProperty("user");String password = pros.getProperty("password");// 3.加载驱动Class.forName(driverClass);// 4.获取连接Connection conn = DriverManager.getConnection(url, user, password);return conn;}//使用c3p0数据库连接池的方式private static ComboPooledDataSource cpds = new ComboPooledDataSource("helloc3p0"); //保证此数据源是唯一的!public static Connection getC3P0Connection() throws SQLException {Connection conn = cpds.getConnection();return conn;}//使用dbcp数据库连接池的方式private static DataSource source;//保证此数据源是唯一的!static{try {Properties pros = new Properties();InputStream is = DBCPTest.class.getClassLoader().getResourceAsStream("dbcp.properties");pros.load(is);source = BasicDataSourceFactory.createDataSource(pros);} catch (Exception e) {e.printStackTrace();}}public static Connection getDBCPConnection() throws SQLException {Connection conn = source.getConnection();return conn;}}

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

演示转账问题

例子:
AA 向 BB 转账 100
过程一:
update user_table set balance = balance - 100 where user = AA.
假设中途服务器宕机
过程二:
update user_table set balance = balance + 100 where user = BB.

注意:最下面是转账失败代码,阅读请留意

package JavaWeb.JDBC.day3.java;import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;import JavaWeb.JDBC.day3.util.JDBCUtils;
import org.junit.Test;public class TransactionTest {// 通用的查询,返回一条记录 (version 2.0)public <T> T getInstance(Connection conn,Class<T> clazz, String sql, Object... args) {PreparedStatement ps = null;ResultSet rs = null;try {// 1.预编译sql语句ps = conn.prepareStatement(sql);// 2.填充占位符for (int i = 0; i < args.length; i++) {ps.setObject(i + 1, args[i]);}// 3.调用executeQuery(),获取结果集rs = ps.executeQuery();// 4.获取结果集的元数据ResultSetMetaData rsmd = rs.getMetaData();// 5.获取结果集中列的个数int columnCount = rsmd.getColumnCount();// 6.处理结果集if (rs.next()) {// ①判断指针的下一个位置是否有数据 ②如果返回true,指针下移。如果返回false,指针不下移。T t = clazz.newInstance();for (int i = 0; i < columnCount; i++) {// 处理列Object columnValue = rs.getObject(i + 1);// 获取列值String columnLabel = rsmd.getColumnLabel(i + 1);// 获取结果集中列的别名// 反射Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columnValue);}return t;}} catch (Exception e) {e.printStackTrace();} finally {// 7.关闭资源JDBCUtils.closeResource(null, ps, rs);}return null;}/** 演示转账操作* */@Testpublic void testUpdateWithTx() {Connection conn = null;try {String sql1 = "update user_table set balance = balance - 100 where user = ?";String sql2 = "update user_table set balance = balance + 100 where user = ?";conn = JDBCUtils.getConnection();//1.设置不能自动提交数据conn.setAutoCommit(false);//过程一:updateWithTx(conn,sql1,"AA");//出现异常System.out.println(10 / 0);//过程二:updateWithTx(conn,sql2,"BB");//2.提交数据conn.commit();System.out.println("转账成功!");} catch (Exception e) {e.printStackTrace();try {//3.回滚数据conn.rollback();} catch (SQLException e1) {e1.printStackTrace();}}finally {if(conn != null) {//关闭连接JDBCUtils.closeResource(conn, null);}}}//通用的增删改 (version 2.0)public void updateWithTx(Connection conn ,String sql, Object... args) {PreparedStatement ps = null;try {// 1.ps = conn.prepareStatement(sql);// 2.填充占位符for(int i = 0;i < args.length;i++) {ps.setObject(i + 1, args[i]);}// 3.执行int count = ps.executeUpdate();System.out.println("影响了" + count + "条数据");} catch (Exception e) {e.printStackTrace();} finally {// 4.连接一定不要关闭!JDBCUtils.closeResource(null, ps,null);}}

在这里插入图片描述
使用2.0版本转账方法发生了事务回滚
在这里插入图片描述
/*
* 1. 数据一旦提交,不可回滚。
* 2. 哪些操作,会导致数据的提交:
* 情况一:执行的DML操作,默认情况下,一旦执行完,就会自动提交数据。 (set autocommit = false)
* 情况二:一旦断开数据库的连接,也会提交之前未提交的数据。
*
*/

	@Testpublic void testUpdate() {String sql1 = "update user_table set balance = balance - 100 where user = ?";String sql2 = "update user_table set balance = balance + 100 where user = ?";update(sql1,"AA");//模拟网络出现阻塞的异常System.out.println(10 / 0);update(sql2,"BB");System.out.println("转账成功");}//通用的增删改 (version 1.0)public void update(String sql, Object... args) {Connection conn = null;PreparedStatement ps = null;try {// 1.conn = JDBCUtils.getConnection();// 2.ps = conn.prepareStatement(sql);// 3.填充占位符for(int i = 0;i < args.length;i++) {ps.setObject(i + 1, args[i]);}			// 4.执行int count = ps.executeUpdate();System.out.println("影响了" + count + "条数据");} catch (Exception e) {e.printStackTrace();} finally {// 5.JDBCUtils.closeResource(conn, ps,null);}}}

在这里插入图片描述
使用1.0版本方法转账失败,没有回滚
在这里插入图片描述

dbutils工具包包下QueryRunner、handlers.BeanHandler、handlers.BeanListHandler、handlers.MapHandler、handlers.ScalarHandler的使用

package JavaWeb.JDBC.day3.java;import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;import JavaWeb.JDBC.day3.bean.Customer;
import JavaWeb.JDBC.day3.util.JDBCUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;public class QueryRunnerTest {//查询一些特殊数据:查询最大值 、 平均数@Testpublic void testScalarValue() throws Exception {QueryRunner runner = new QueryRunner();Connection conn = JDBCUtils.getConnection();ScalarHandler handler = new ScalarHandler();//需求一:查询birth的最大值
//		String sql = "select max(birth) from customers";
//		Date birth = (Date) runner.query(conn, sql, handler);
//		System.out.println(birth);//需求二:查询表中的数据的数量String sql = "select count(*) from customers";long count = (long) runner.query(conn, sql, handler);System.out.println(count);JDBCUtils.closeResource(conn, null);
}

在这里插入图片描述

//查询表中的一条记录,以key-value的方式显示
@Test
public void testQueryForMap() throws Exception {QueryRunner runner = new QueryRunner();Connection conn = JDBCUtils.getConnection();String sql = "select id,name,email,birth from customers where id = ?";MapHandler handler = new MapHandler();Map<String, Object> map = runner.query(conn, sql, handler, 6);System.out.println(map);JDBCUtils.closeResource(conn, null);
}

在这里插入图片描述

//查询表中的多条记录构成的集合:BeanListHandler
@Test
public void testQueryForList() throws Exception {QueryRunner runner = new QueryRunner();Connection conn = JDBCUtils.getConnection();String sql = "select id,name,email,birth from customers where id < ?";BeanListHandler<Customer> handler = new BeanListHandler<>(Customer.class);List<Customer> list = runner.query(conn, sql, handler, 10);list.forEach(System.out::println);JDBCUtils.closeResource(conn, null);
}

在这里插入图片描述

//查询表中的一条记录:BeanHandler
@Test
public void testQueryInstance() throws Exception {QueryRunner runner = new QueryRunner();Connection conn = JDBCUtils.getConnection();String sql = "select id,name,email,birth from customers where id = ?";BeanHandler<Customer> handler = new BeanHandler<>(Customer.class);Customer customer = runner.query(conn, sql, handler, 6);System.out.println(customer);JDBCUtils.closeResource(conn, null);
}

在这里插入图片描述

@Test
public void testInsert() {Connection conn = null;try {QueryRunner runner = new QueryRunner();conn = JDBCUtils.getC3P0Connection();String sql = "insert into customers(name,email,birth)values(?,?,?)";//调用如下的update()方法实现增、删、改的操作runner.update(conn, sql,"张三","zhangsan@gmail.com","2019-08-04");} catch (SQLException e) {e.printStackTrace();}JDBCUtils.closeResource(conn, null);
}
}

插入成功
在这里插入图片描述
以上是JDBC重点,下面介绍c3p0与dbcp连接池

使用 c3p0数据库连接池技术实现数据库连接

package JavaWeb.JDBC.day3.connection;import java.sql.Connection;
import java.sql.SQLException;import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.junit.Test;

/**

  • 1.实现数据库连接的方式:
  • ① 手动实现的连接 (DriverManager)
  • ② 使用数据库连接池
  • 2.使用数据库连接池的好处:
  • ① 更快的连接速度
  • ② 更好的资源重用
  • ③ 更便捷的数据库连接的管理
  • 3.JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口

*4.两种数据库连接池技术:
① C3P0 数据库连接池 ② DBCP数据库连接池
*/

public class C3P0Test {//方式二:使用配置文件
@Test
public void testConnection2() throws SQLException {ComboPooledDataSource cpds = new ComboPooledDataSource("helloc3p0");Connection conn = cpds.getConnection();System.out.println(conn);	
}//方式一:
@Test
public void testConnection1() throws Exception {ComboPooledDataSource cpds = new ComboPooledDataSource();cpds.setDriverClass( "com.mysql.jdbc.Driver" ); cpds.setJdbcUrl( "jdbc:mysql://localhost:3306/test" );cpds.setUser("root");                                  cpds.setPassword("abc123");//cpds.setMaxPoolSize(100);Connection conn = cpds.getConnection();System.out.println(conn);
}}

在这里插入图片描述
c3p0配置文件代码
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config><named-config name="helloc3p0"><!-- 数据库连接的4个基本信息 --><property name="driverClass">com.mysql.jdbc.Driver</property><property name="jdbcUrl">jdbc:mysql:///test</property><property name="user">root</property><property name="password">abc123</property><!-- 涉及数据库连接池管理的其他信息 --><!-- 当数据库连接池中的连接不足时,c3p0数据源一次性向数据库服务器申请的连接数 --><property name="acquireIncrement">5</property><!-- 初始化时,数据库连接池中的连接数 --><property name="initialPoolSize">10</property><!-- 连接池中最少的连接数 --><property name="minPoolSize">10</property><!-- 数据库连接池中维护的连接数的最大容量 --><property name="maxPoolSize">100</property><!-- 数据库连接池中,最多维护的Statement的个数 --><property name="maxStatements">50</property><!-- 一次连接中最多可以使用的Statement的个数 --><property name="maxStatementsPerConnection">2</property></named-config>
</c3p0-config>

使用DBCP数据库连接池技术实现数据库连接

package JavaWeb.JDBC.day3.connection;import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;import javax.sql.DataSource;import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test;/*** 使用DBCP数据库连接池技术实现数据库连接* @author Administrator**/
public class DBCPTest {//方式二:使用配置文件@Testpublic void testGetConnection2() throws Exception {Properties pros = new Properties();//方式1:
//		FileInputStream is = new FileInputStream("src/dbcp.properties");//方式2:InputStream is = DBCPTest.class.getClassLoader().getResourceAsStream("dbcp.properties");pros.load(is);DataSource source = BasicDataSourceFactory.createDataSource(pros);Connection conn = source.getConnection();System.out.println(conn);
}//方式一:
@Test
public void testGetConnection1() throws SQLException {BasicDataSource source = new BasicDataSource();source.setDriverClassName("com.mysql.jdbc.Driver");source.setUrl("jdbc:mysql://localhost:3306/test");source.setUsername("root");source.setPassword("abc123");//source.setInitialSize(10);//...Connection conn = source.getConnection();System.out.println(conn);
}}

在这里插入图片描述
dbcp配置文件则要简单很多,看不懂请学下io流的properties
在这里插入图片描述

driverClassName=com.mysql.jdbc.Driver
url=Jdbc:mysql:///test
username=root
password=abc123

DAO

DAO: data(base) access object 数据访问对象

不考虑事务的DAO1.0介绍

package JavaWeb.JDBC.day3.dao;import JavaWeb.JDBC.day3.util.JDBCUtils;import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;public class DAO {// 通用的查询,返回多条记录 (version 2.0:考虑到事务)public <T> List<T> getForList(Connection conn, Class<T> clazz, String sql, Object... args) {PreparedStatement ps = null;ResultSet rs = null;List<T> list = new ArrayList<>();try {// 1.预编译sql语句ps = conn.prepareStatement(sql);// 2.填充占位符for (int i = 0; i < args.length; i++) {ps.setObject(i + 1, args[i]);}// 3.调用executeQuery(),获取结果集rs = ps.executeQuery();// 4.获取结果集的元数据ResultSetMetaData rsmd = rs.getMetaData();// 5.获取结果集中列的个数int columnCount = rsmd.getColumnCount();// 6.处理结果集while (rs.next()) {// ①判断指针的下一个位置是否有数据 ②如果返回true,指针下移。如果返回false,指针不下移。T t = clazz.newInstance();for (int i = 0; i < columnCount; i++) {// 处理列Object columnValue = rs.getObject(i + 1);// 获取列值String columnLabel = rsmd.getColumnLabel(i + 1);// 获取结果集中列的别名// 反射Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columnValue);}list.add(t);}return list;} catch (Exception e) {e.printStackTrace();} finally {// 7.关闭资源JDBCUtils.closeResource(null, ps, rs);}	return null;}// 通用的查询,返回一条记录 (version 2.0:考虑到事务)public <T> T getInstance(Connection conn, Class<T> clazz, String sql, Object... args) {PreparedStatement ps = null;ResultSet rs = null;try {// 1.预编译sql语句ps = conn.prepareStatement(sql);// 2.填充占位符for (int i = 0; i < args.length; i++) {ps.setObject(i + 1, args[i]);}// 3.调用executeQuery(),获取结果集rs = ps.executeQuery();// 4.获取结果集的元数据ResultSetMetaData rsmd = rs.getMetaData();// 5.获取结果集中列的个数int columnCount = rsmd.getColumnCount();// 6.处理结果集if (rs.next()) {// ①判断指针的下一个位置是否有数据 ②如果返回true,指针下移。如果返回false,指针不下移。T t = clazz.newInstance();for (int i = 0; i < columnCount; i++) {// 处理列Object columnValue = rs.getObject(i + 1);// 获取列值String columnLabel = rsmd.getColumnLabel(i + 1);// 获取结果集中列的别名// 反射Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columnValue);}return t;}} catch (Exception e) {e.printStackTrace();} finally {// 7.关闭资源JDBCUtils.closeResource(null, ps, rs);}return null;}// 通用的增删改 (version 2.0:考虑到事务)public void update(Connection conn, String sql, Object... args) {PreparedStatement ps = null;try {// 1.ps = conn.prepareStatement(sql);// 2.填充占位符for (int i = 0; i < args.length; i++) {ps.setObject(i + 1, args[i]);}// 3.执行int count = ps.executeUpdate();System.out.println("影响了" + count + "条数据");} catch (Exception e) {e.printStackTrace();} finally {// 4.连接一定不要关闭!JDBCUtils.closeResource(null, ps, null);}}
}

创建CustomerDAO类继承DAO,添加对customers表的增删改查方法
package JavaWeb.JDBC.day3.dao;

import JavaWeb.JDBC.day3.bean.Customer;import java.sql.Connection;
import java.util.List;public class CustomerDAO extends DAO{/*** 查询表中的所有记录* @param conn* @return*/public List<Customer> getAll(Connection conn){String sql = "select id,name,email,birth from customers ";List<Customer> list = getForList(conn, Customer.class, sql);return list;}/*** 查询指定id的对象* @param conn* @param id* @return*/public Customer getById(Connection conn,int id) {String sql = "select id,name,email,birth from customers where id = ?";Customer customer = getInstance(conn,Customer.class, sql, id);return customer;}/*** 修改数据表中的一条记录* @param conn* @param cust*/public void updateCustomer(Connection conn,Customer cust) {//cust = new Customer(10,"迪丽热巴",..,..)String sql = "update customers set name = ?,email = ?,birth = ? where id = ?";update(conn, sql,cust.getName(),cust.getEmail(),cust.getBirth(),cust.getId());}/*** 删除数据表中指定id对应的数据* @param conn* @param id*/public void deleteById(Connection conn,int id) {String sql = "delete from customers where id = ?";update(conn, sql,id);}/*** 向customers表中插入一条数据* @param conn* @param cust*/public void addCustomer(Connection conn,Customer cust) {String sql = "insert into customers(name,email,birth)values(?,?,?)";update(conn, sql,cust.getName(),cust.getEmail(),cust.getBirth());}
}

创建CustomerDAO的测试类CustomerDAOTest测试类测试以上方法
package JavaWeb.JDBC.day3.dao;

import java.sql.Connection;
import java.sql.Date;
import java.util.List;import JavaWeb.JDBC.day3.bean.Customer;
import JavaWeb.JDBC.day3.util.JDBCUtils;
import org.junit.Test;/*** CustomerDAO的测试类**/
public class CustomerDAOTest {@Testpublic void testGetAll() throws Exception {CustomerDAO dao = new CustomerDAO();//		Connection conn = JDBCUtils.getConnection();
//		Connection conn = JDBCUtils.getC3P0Connection();Connection conn = JDBCUtils.getDBCPConnection();List<Customer> list = dao.getAll(conn);list.forEach(System.out::println);JDBCUtils.closeResource(conn, null);}

在这里插入图片描述

	@Testpublic void testGetOne() throws Exception {CustomerDAO dao = new CustomerDAO();Connection conn = JDBCUtils.getConnection();Customer cust = dao.getById(conn, 8);System.out.println(cust);JDBCUtils.closeResource(conn, null);}

在这里插入图片描述

	@Testpublic void testAdd() throws Exception {CustomerDAO dao = new CustomerDAO();Connection conn = JDBCUtils.getConnection();Customer cust = new Customer(1,"任鑫","ren@126.com",new Date(1242423423L));dao.addCustomer(conn, cust);JDBCUtils.closeResource(conn, null);}}

在这里插入图片描述
添加成功
在这里插入图片描述

考虑事务的DAO2.0介绍

反射工具类ReflectionUtil 准备

package JavaWeb.JDBC.day3.dao1;import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;public class ReflectionUtil {//反射的工具类/*** 获取形参clazz的父类的泛型* @param clazz* @return*/public static Class getGenericParam(Class clazz) {//Class clazz = CustomerDAO.classType type = clazz.getGenericSuperclass();ParameterizedType paramType = (ParameterizedType) type;Type[] typeArguments = paramType.getActualTypeArguments();//返回泛型参数构成的数组return (Class) typeArguments[0];}
}

DAO2.0代码(考虑事务)
package JavaWeb.JDBC.day3.dao1;

import JavaWeb.JDBC.day3.util.JDBCUtils;import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;/** DAO: data(base) access object 数据访问对象*/
public class DAO<T> {private Class<T>  clazz = null;{//给clazz赋值clazz = ReflectionUtil.getGenericParam(this.getClass());//比如:CustomerDAO}// 通用的查询,返回一条记录 (version 2.0:考虑到事务)public List<T> getForList(Connection conn, String sql, Object... args) {PreparedStatement ps = null;ResultSet rs = null;List<T> list = new ArrayList<>();try {// 1.预编译sql语句ps = conn.prepareStatement(sql);// 2.填充占位符for (int i = 0; i < args.length; i++) {ps.setObject(i + 1, args[i]);}// 3.调用executeQuery(),获取结果集rs = ps.executeQuery();// 4.获取结果集的元数据ResultSetMetaData rsmd = rs.getMetaData();// 5.获取结果集中列的个数int columnCount = rsmd.getColumnCount();// 6.处理结果集while (rs.next()) {// ①判断指针的下一个位置是否有数据 ②如果返回true,指针下移。如果返回false,指针不下移。T t = clazz.newInstance();for (int i = 0; i < columnCount; i++) {// 处理列Object columnValue = rs.getObject(i + 1);// 获取列值String columnLabel = rsmd.getColumnLabel(i + 1);// 获取结果集中列的别名// 反射Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columnValue);}list.add(t);}return list;} catch (Exception e) {e.printStackTrace();} finally {// 7.关闭资源JDBCUtils.closeResource(null, ps, rs);}return null;}// 通用的查询,返回一条记录 (version 2.0:考虑到事务)public T getInstance(Connection conn,  String sql, Object... args) {PreparedStatement ps = null;ResultSet rs = null;try {// 1.预编译sql语句ps = conn.prepareStatement(sql);// 2.填充占位符for (int i = 0; i < args.length; i++) {ps.setObject(i + 1, args[i]);}// 3.调用executeQuery(),获取结果集rs = ps.executeQuery();// 4.获取结果集的元数据ResultSetMetaData rsmd = rs.getMetaData();// 5.获取结果集中列的个数int columnCount = rsmd.getColumnCount();// 6.处理结果集if (rs.next()) {// ①判断指针的下一个位置是否有数据 ②如果返回true,指针下移。如果返回false,指针不下移。T t = clazz.newInstance();for (int i = 0; i < columnCount; i++) {// 处理列Object columnValue = rs.getObject(i + 1);// 获取列值String columnLabel = rsmd.getColumnLabel(i + 1);// 获取结果集中列的别名// 反射Field field = clazz.getDeclaredField(columnLabel);field.setAccessible(true);field.set(t, columnValue);}return t;}} catch (Exception e) {e.printStackTrace();} finally {// 7.关闭资源JDBCUtils.closeResource(null, ps, rs);}return null;}// 通用的增删改 (version 2.0:考虑到事务)public void update(Connection conn, String sql, Object... args) {PreparedStatement ps = null;try {// 1.ps = conn.prepareStatement(sql);// 2.填充占位符for (int i = 0; i < args.length; i++) {ps.setObject(i + 1, args[i]);}// 3.执行int count = ps.executeUpdate();System.out.println("影响了" + count + "条数据");} catch (Exception e) {e.printStackTrace();} finally {// 4.连接一定不要关闭!JDBCUtils.closeResource(null, ps, null);}}
}

另外两个CustomerDAO和CustomerDAOTest类代码不变

这篇关于JavaWeb之JDBC(2.2):数据库事务、数据库连接池、DBUtils、DAO及其子类代码演示的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/839747

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听