当前位置:网站首页>JDBC原理
JDBC原理
2022-07-06 09:13:00 【丸酸菌】
数据库连接方式
如果是如果驱动包版本是8.x的话,properties文件中的driverClass的路径就是com.mysql.cj.jdbc.Driver,不是原来的com.mysql.jdbc.Driver
方式一:Driver实现类对象获取连接
@Test
public void testConnection1() throws SQLException {
// 获取Driver实现类对象
Driver driver = new com.mysql.jdbc.Driver();
// url:jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
// `jdbc:mysql`:协议
// localhost:ip地址
// 3306:默认mysql的端口号
// test:test数据库
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8";
// 将用户名和密码封装在Properties中
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "abc123");
Connection conn = driver.connect(url, info);
System.out.println(conn);
}
说明:上述代码中显式出现了第三方数据库的API
方式二:“方式一的迭代”,不出现第三方的api使得程序具有更好的可移植性
@Test
public void testConnection2() throws Exception {
// 1.获取Driver实现类对象:使用反射
//调用Class的静态方法获取Class类的实例:forName(String classPath)
Class clazz = Class.forName("com.mysql.jdbc.Driver");
//调用Class对象的newInstance()方法获取运行时类(new com.mysql.jdbc.Driver())的对象
Driver driver = (Driver) clazz.newInstance();
// 2.提供要连接的数据库
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8";
// 3.提供连接需要的用户名和密码
Properties info = new Properties();
info.setProperty("user", "root");
info.setProperty("password", "abc123");
// 4.获取连接
Connection conn = driver.connect(url, info);
System.out.println(conn);
}
说明:相较于方式一,这里使用反射实例化Driver,不在代码中体现第三方数据库的API。体现了面向接口编程思想。
方式三:DriverManager替换Driver
@Test
public void testConnection3() throws Exception {
// 1.获取Driver实现类的对象
Class clazz = Class.forName("com.mysql.jdbc.Driver");
Driver driver = (Driver) clazz.newInstance();
// 2.提供另外三个连接的基本信息:
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "abc123";
// 注册驱动
DriverManager.registerDriver(driver);
// 获取连接
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
}
说明:使用DriverManager实现数据库的连接。体会获取连接必要的4个基本要素。
方式四:加载驱动,不用显示注册驱动。
@Test
public void testConnection4() throws Exception {
// 1.提供三个连接的基本信息:
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8";
String user = "root";
String password = "abc123";
// 2.加载Driver
Class.forName("com.mysql.jdbc.Driver");
//相较于方式三,可以省略如下的操作:
// Driver driver = (Driver) clazz.newInstance();
// // 注册驱动
// DriverManager.registerDriver(driver);
//为什么可以省略上述操作呢?
/* * 在mysql的Driver实现类中,声明了如下的操作: * static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw new RuntimeException("Can't register driver!"); } } */
// 3.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
}
说明:不必显式的注册驱动了。因为在DriverManager的源码中已经存在静态代码块,实现了驱动的注册。
方式五(final版):将数据库连接需要的4个基本信息声明在配置文件中,通过读取配置文件的方式,获取连接
/*此种方式的好处? * 1.实现了数据与代码的分离。实现了解耦 * 2.如果需要修改配置文件信息,可以避免程序重新打包。*/
@Test
public void getConnection5() throws Exception{
//1.读取配置文件中的4个基本信息
//.class获取Class类的实例
//getClassLoader获取类的系统类加载器
//getResourceAsStream获取类路径下的指定文件的输入流
InputStream is = ConnectionTest.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
//2.加载驱动--加载Driver
Class.forName(driverClass);
// 注册驱动 Driver实现类中声明了静态代码块
//3.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
其中,配置文件声明在工程的src目录下:【jdbc.properties】
user=root
password=abc123
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
driverClass=com.mysql.jdbc.Driver
说明:使用配置文件的方式保存配置信息,在代码中加载配置文件
使用配置文件的好处:
①实现了代码和数据的分离,如果需要修改配置信息,直接在配置文件中修改,不需要深入代码
②如果修改了配置信息,省去重新编译的过程。
PreparedStatement查询
jdbc.properties
user=root
password=abc123
url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
driverClass=com.mysql.jdbc.Driver
针对于Customers表的增删改操作
public class PreparedStatementUpdateTest {
//修改customers表的一条记录
@Test
public void testUpdate(){
Connection conn = null;
PreparedStatement ps = null;
try {
//1.获取数据库的连接
conn = JDBCUtils.getConnection();
//2.预编译sql语句,返回PreparedStatement的实例
String sql = "update customers set name = ? where id = ?";
ps = conn.prepareStatement(sql);
//3.填充占位符
ps.setObject(1,"莫扎特");
ps.setObject(2, 18);
//4.执行
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally{
//5.资源的关闭
JDBCUtils.closeResource(conn, ps);
}
}
// 向customers表中添加一条记录
@Test
public void testInsert() {
Connection conn = null;
PreparedStatement ps = null;
try {
// 1.读取配置文件中的4个基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
// 2.加载驱动
Class.forName(driverClass);
// 3.获取连接
conn = DriverManager.getConnection(url, user, password);
//4.预编译sql语句,返回PreparedStatement的实例
String sql = "insert into customers(name,email,birth)values(?,?,?)";//?:占位符
ps = conn.prepareStatement(sql);
//5.填充占位符
ps.setString(1, "哪吒");
ps.setString(2, "[email protected]");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date = sdf.parse("1000-01-01");
ps.setDate(3, new Date(date.getTime()));
//6.执行操作
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally{
//7.资源的关闭
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
封装JDBCUtils
public class JDBCUtils {
/** * @Description 获取数据库的连接 */
public static Connection getConnection() throws Exception {
// 1.读取配置文件中的4个基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
// 2.加载驱动
Class.forName(driverClass);
// 3.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
/** * @Description 关闭连接和Statement的操作 */
public static void closeResource(Connection conn,Statement ps){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/** * @Description 关闭资源操作 */
public static void closeResource(Connection conn,Statement ps,ResultSet rs){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
针对于Customers表通用的增删改
//通用的增删改操作
public void update(String sql,Object ...args){
//sql中占位符的个数与可变形参的长度相同!
Connection conn = null;
PreparedStatement ps = null;
try {
//1.获取数据库的连接
conn = JDBCUtils.getConnection();
//2.预编译sql语句,返回PreparedStatement的实例
ps = conn.prepareStatement(sql);
//3.填充占位符
for(int i = 0;i < args.length;i++){
ps.setObject(i + 1, args[i]);//小心参数声明错误!!
}
//4.执行
ps.execute();
} catch (Exception e) {
e.printStackTrace();
}finally{
//5.资源的关闭
JDBCUtils.closeResource(conn, ps);
}
}
针对于Customers表的查询操作返回一条记录
public class CustomerForQuery {
@Test
public void testQuery1() {
Connection conn = null;
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
conn = JDBCUtils.getConnection();
String sql = "select id,name,email,birth from customers where id = ?";
ps = conn.prepareStatement(sql);
ps.setObject(1, 1);
// 执行,并返回结果集
resultSet = ps.executeQuery();
// 处理结果集
if (resultSet.next()) {
// next():判断结果集的下一条是否有数据,如果有数据返回true,并指针下移;如果返回false,指针不会下移。
// 获取当前这条数据的各个字段值
int id = resultSet.getInt(1);
String name = resultSet.getString(2);
String email = resultSet.getString(3);
Date birth = resultSet.getDate(4);
// 方式一:
// System.out.println("id = " + id + ",name = " + name + ",email = " + email + ",birth = " + birth);
// 方式二:
// Object[] data = new Object[]{id,name,email,birth};
// 方式三:将数据封装为一个对象(推荐)
Customer customer = new Customer(id, name, email, birth);
System.out.println(customer);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, resultSet);
}
}
//-------------------------------------------------------------------
针对于Customers表的通用的查询操作
public Customer queryForCustomers(String sql, Object... args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
// 获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
Customer cust = new Customer();
// 处理结果集一行数据中的每一个列
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object columValue = rs.getObject(i + 1);
// 获取每个列的列名
// String columnName = rsmd.getColumnName(i + 1);
String columnLabel = rsmd.getColumnLabel(i + 1);
// 给cust对象指定的columnName属性,赋值为columValue:通过反射
Field field = Customer.class.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(cust, columValue);
}
return cust;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(conn, ps, rs);
}
return null;
}
@Test
public void testQueryForCustomers() {
String sql = "select id,name,birth,email from customers where id = ?";
Customer customer = queryForCustomers(sql, 13);
System.out.println(customer);
sql = "select name,email from customers where name = ?";
Customer customer1 = queryForCustomers(sql, "周杰伦");
System.out.println(customer1);
}
}
未考虑数据库事务通用的增删改
// ******************未考虑数据库事务情况下的转账操作**************************
/* * 针对于数据表user_table来说: AA用户给BB用户转账100 * * update user_table set balance = balance - 100 where user = 'AA'; update * user_table set balance = balance + 100 where user = 'BB'; */
@Test
public void testUpdate() {
String sql1 = "update user_table set balance = balance - 100 where user = ?";
update(sql1, "AA");
// 模拟网络异常
System.out.println(10 / 0);
String sql2 = "update user_table set balance = balance + 100 where user = ?";
update(sql2, "BB");
System.out.println("转账成功");
}
// 通用的增删改操作---version 1.0
public int update(String sql, Object... args) {
// sql中占位符的个数与可变形参的长度相同!
Connection conn = null;
PreparedStatement ps = null;
try {
// 1.获取数据库的连接
conn = JDBCUtils.getConnection();
// 2.预编译sql语句,返回PreparedStatement的实例
ps = conn.prepareStatement(sql);
// 3.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);// 小心参数声明错误!!
}
// 4.执行
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 修改其为自动提交数据
// 主要针对于使用数据库连接池的使用
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
// 5.资源的关闭
JDBCUtils.closeResource(conn, ps);
}
return 0;
}
考虑数据库事务后通用的增删改
@Test
public void testUpdateWithTx() {
Connection conn = null;
try {
conn = JDBCUtils.getConnection();
System.out.println(conn.getAutoCommit());// true
// 1.取消数据的自动提交
conn.setAutoCommit(false);
String sql1 = "update user_table set balance = balance - 100 where user = ?";
update(conn, sql1, "AA");
// 模拟网络异常
System.out.println(10 / 0);
String sql2 = "update user_table set balance = balance + 100 where user = ?";
update(conn, sql2, "BB");
System.out.println("转账成功");
// 2.提交数据
conn.commit();
} catch (Exception e) {
e.printStackTrace();
// 3.回滚数据
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
} finally {
JDBCUtils.closeResource(conn, null);
}
}
//-------------------------------------------------------------------
// 通用的增删改操作---version 2.0 (考虑上事务)
public int update(Connection conn, String sql, Object... args) {
// sql中占位符的个数与可变形参的长度相同!
PreparedStatement ps = null;
try {
// 1.预编译sql语句,返回PreparedStatement的实例
ps = conn.prepareStatement(sql);
// 2.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);// 小心参数声明错误!!
}
// 3.执行
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 4.资源的关闭
JDBCUtils.closeResource(null, ps);
}
return 0;
}
考虑数据库事务后通用的查询
public <T> T getInstance(Connection conn, Class<T> clazz, String sql, Object... args) {
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
// 获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
if (rs.next()) {
T t = clazz.newInstance();
// 处理结果集一行数据中的每一个列
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object columValue = rs.getObject(i + 1);
// 获取每个列的列名
// String columnName = rsmd.getColumnName(i + 1);
String columnLabel = rsmd.getColumnLabel(i + 1);
// 给t对象指定的columnName属性,赋值为columValue:通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columValue);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(null, ps, rs);
}
return null;
}
JDBCUtils(含连接池)
public class JDBCUtils {
/** * @Description 获取数据库的连接 */
public static Connection getConnection() throws Exception {
// 1.读取配置文件中的4个基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
// 2.加载驱动
Class.forName(driverClass);
// 3.获取连接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
//-------------------------------------------------------------------
/** * 使用Druid数据库连接池技术 */
private static DataSource source;
static{
try {
Properties pros = new Properties();
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties");
pros.load(is);
source = DruidDataSourceFactory.createDataSource(pros);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection1() throws SQLException{
Connection conn = source.getConnection();
return conn;
}
//-------------------------------------------------------------------
/** * @Description 使用DBCP数据库连接池技术获取数据库连接 */
//创建一个DBCP数据库连接池
private static DataSource source1;
static{
try {
Properties pros = new Properties();
FileInputStream is = new FileInputStream(new File("src/dbcp.properties"));
pros.load(is);
source1 = BasicDataSourceFactory.createDataSource(pros);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection2() throws Exception{
Connection conn = source1.getConnection();
return conn;
}
//-------------------------------------------------------------------
/** * @Description 使用C3P0的数据库连接池技术 */
//数据库连接池只需提供一个即可。
private static ComboPooledDataSource cpds = new ComboPooledDataSource("hellc3p0");
public static Connection getConnection4() throws SQLException{
Connection conn = cpds.getConnection();
return conn;
}
//-------------------------------------------------------------------
//-------------------------------------------------------------------
//-------------------------------------------------------------------
/** * @Description 关闭连接和Statement的操作 */
public static void closeResource(Connection conn,Statement ps){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/** * @Description 关闭ResultSet结果集资源操作 */
public static void closeResource(Connection conn,Statement ps,ResultSet rs){
try {
if(ps != null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(rs != null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//-------------------------------------------------------------------
/** * @Description 使用dbutils.jar中提供的DbUtils工具类,实现资源的关闭 */
public static void closeResource1(Connection conn,Statement ps,ResultSet rs){
// try {
// DbUtils.close(conn);
// } catch (SQLException e) {
// e.printStackTrace();
// }
// try {
// DbUtils.close(ps);
// } catch (SQLException e) {
// e.printStackTrace();
// }
// try {
// DbUtils.close(rs);
// } catch (SQLException e) {
// e.printStackTrace();
// }
DbUtils.closeQuietly(conn);
DbUtils.closeQuietly(ps);
DbUtils.closeQuietly(rs);
}
}
BaseDAO/DAO
DAO: data(base) access object
/** * 封装了针对于数据库进行通用的基本操作 */
public abstract class BaseDAO<T> {
//获取泛型T的Class对象,获取泛型的类型,泛型是在被子类继承时才确定
private Class<T> clazz ;
// public BaseDAO(){
//
// }
{
//通过this获取所属类再获取所属类的父类,在强转成带泛型的父类,在获取泛型数组,再取第一个泛型类型
//因为此类是抽象类被子类继承,当子类对象被创建时会调用父类构造函数时调用静态方法或者构造器方法
//此时传递的this值是调用类的值也就是继承类的值或者说是继承父类的子类的值)
// this.getClass()获取调用父类的子类类型
// getGenericSuperclass()用来获取当前类的父类的类型
//获取当前BaseDAO的子类继承的父类中的泛型
Type genericSuperclass = this.getClass().getGenericSuperclass();
// ParameterizedType表示的是带泛型的类型
ParameterizedType paramType = (ParameterizedType) genericSuperclass;
//获取了父类的泛型参数
// getActualTypeArguments获取具体的泛型的类型
// 这个方法会返回一个Type类型的泛型数组
Type[] typeArguments = paramType.getActualTypeArguments();
//获取具体的泛型的类型·泛型的第一个参数
clazz = (Class<T>) typeArguments[0];
}
//-------------------------------------------------------------------
// 通用的增删改操作---version 2.0 (考虑上事务)
public int update(Connection conn, String sql, Object... args) {
// sql中占位符的个数与可变形参的长度相同!
PreparedStatement ps = null;
try {
// 1.获取PreparedStatement的实例,预编译sql语句
ps = conn.prepareStatement(sql);
// 2.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);//Object防止参数声明错误
}
// 3.执行executeUpdate返回操作行数
return ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
// 4.资源的关闭
JDBCUtils.closeResource(null, ps);
}
return 0;
}
//-------------------------------------------------------------------
// 通用的查询操作,用于返回数据表中的一条记录(version 2.0:考虑上事务)
public T getInstance(Connection conn, String sql, Object... args) {
//
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 1.获取PreparedStatement()的实例,预编译sql语句
ps = conn.prepareStatement(sql);
// 2.填充占位符
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
// 3.执行executeQuery()返回ResultSet结果集对象
rs = ps.executeQuery();
// getMetaData()获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 通过元数据getColumnCount()获取结果集中的列数
int columnCount = rsmd.getColumnCount();
// 4.处理结果集行数据,判断结果集的下一条是否有数据,如果有数据返回true,并指针下移;如果返回false,指针不会下移。
if (rs.next()) {
//创建返回值T类型的对象
T t = clazz.getDeclaredConstructor().newInstance();
// 5. 处理结果集一行数据中的每一个列
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object columValue = rs.getObject(i + 1);
// 获取每个列的列名
// String columnName = rsmd.getColumnName(i + 1);
String columnLabel = rsmd.getColumnLabel(i + 1);
// 给t对象指定的columnLabel属性,赋值为columValue:通过反射
//当前clazz的值是子类继承父类中定义泛型的值(详细看代码头部)
//getDeclaredField()调用私有的属性,获取运行时类中指定变量名的属性
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columValue);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(null, ps, rs);
}
return null;
}
//-------------------------------------------------------------------
// 通用的查询操作,用于返回数据表中的多条记录构成的集合(version 2.0:考虑上事务)
public List<T> getForList(Connection conn, String sql, Object... args) {
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
// 获取结果集的元数据 :ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
// 通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
// 创建集合对象
ArrayList<T> list = new ArrayList<T>();
while (rs.next()) {
T t = clazz.getDeclaredConstructor().newInstance();
// 处理结果集一行数据中的每一个列:给t对象指定的属性赋值
for (int i = 0; i < columnCount; i++) {
// 获取列值
Object columValue = rs.getObject(i + 1);
// 获取每个列的列名
// String columnName = rsmd.getColumnName(i + 1);
String columnLabel = rsmd.getColumnLabel(i + 1);
// 给t对象指定的columnName属性,赋值为columValue:通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t, columValue);
}
list.add(t);
}
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(null, ps, rs);
}
return null;
}
//-------------------------------------------------------------------
//用于查询特殊值的通用的方法
public <E> E getValue(Connection conn,String sql,Object...args){
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(sql);
for(int i = 0;i < args.length;i++){
ps.setObject(i + 1, args[i]);
}
rs = ps.executeQuery();
if(rs.next()){
return (E) rs.getObject(1);
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.closeResource(null, ps, rs);
}
return null;
}
}
DbUtils
/* * commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,封装了针对于数据库的增删改查操作 * */
public class QueryRunnerTest {
//测试插入
@Test
public void testInsert() {
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection3();
String sql = "insert into customers(name,email,birth)values(?,?,?)";
int insertCount = runner.update(conn, sql, "蔡徐坤","[email protected]","1997-09-08");
System.out.println("添加了" + insertCount + "条记录");
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, null);
}
}
//测试查询
/* * BeanHander:是ResultSetHandler接口的实现类,用于封装表中的一条记录。 */
@Test
public void testQuery1(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection3();
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, 23);
System.out.println(customer);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, null);
}
}
/* * BeanListHandler:是ResultSetHandler接口的实现类,用于封装表中的多条记录构成的集合。 */
@Test
public void testQuery2() {
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection3();
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, 23);
list.forEach(System.out::println);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, null);
}
}
/* * MapHander:是ResultSetHandler接口的实现类,对应表中的一条记录。 * 将字段及相应字段的值作为map中的key和value */
@Test
public void testQuery3(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection3();
String sql = "select id,name,email,birth from customers where id = ?";
MapHandler handler = new MapHandler();
Map<String, Object> map = runner.query(conn, sql, handler, 23);
System.out.println(map);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, null);
}
}
/* * MapListHander:是ResultSetHandler接口的实现类,对应表中的多条记录。 * 将字段及相应字段的值作为map中的key和value。将这些map添加到List中 */
@Test
public void testQuery4(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection3();
String sql = "select id,name,email,birth from customers where id < ?";
MapListHandler handler = new MapListHandler();
List<Map<String, Object>> list = runner.query(conn, sql, handler, 23);
list.forEach(System.out::println);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, null);
}
}
/* * ScalarHandler:用于查询特殊值 */
@Test
public void testQuery5(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection3();
String sql = "select count(*) from customers";
ScalarHandler handler = new ScalarHandler();
Long count = (Long) runner.query(conn, sql, handler);
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, null);
}
}
@Test
public void testQuery6(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection3();
String sql = "select max(birth) from customers";
ScalarHandler handler = new ScalarHandler();
Date maxBirth = (Date) runner.query(conn, sql, handler);
System.out.println(maxBirth);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, null);
}
}
/* * 自定义ResultSetHandler的实现类 */
@Test
public void testQuery7(){
Connection conn = null;
try {
QueryRunner runner = new QueryRunner();
conn = JDBCUtils.getConnection3();
String sql = "select id,name,email,birth from customers where id = ?";
ResultSetHandler<Customer> handler = new ResultSetHandler<Customer>(){
@Override
public Customer handle(ResultSet rs) throws SQLException {
// System.out.println("handle");
// return null;
// return new Customer(12, "成龙", "[email protected]", new Date(234324234324L));
if(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
Date birth = rs.getDate("birth");
Customer customer = new Customer(id, name, email, birth);
return customer;
}
return null;
}
};
Customer customer = runner.query(conn, sql, handler,23);
System.out.println(customer);
} catch (SQLException e) {
e.printStackTrace();
}finally{
JDBCUtils.closeResource(conn, null);
}
}
}
边栏推荐
- Mysql28 database design specification
- Mysql27 index optimization and query optimization
- 数据库中间件_Mycat总结
- How to find the number of daffodils with simple and rough methods in C language
- Other new features of mysql18-mysql8
- MySQL20-MySQL的数据目录
- MySQL21-用户与权限管理
- Pytorch RNN actual combat case_ MNIST handwriting font recognition
- Unicode decodeerror: 'UTF-8' codec can't decode byte 0xd0 in position 0 successfully resolved
- Mysql32 lock
猜你喜欢
Mysql25 index creation and design principles
Mysql21 - gestion des utilisateurs et des droits
Mysql36 database backup and recovery
1. Mx6u learning notes (VII): bare metal development (4) -- master frequency and clock configuration
CSDN blog summary (I) -- a simple first edition implementation
【博主推荐】asp.net WebService 后台数据API JSON(附源码)
MySQL25-索引的创建与设计原则
Some problems in the development of unity3d upgraded 2020 VR
CSDN markdown editor
MySQL36-数据库备份与恢复
随机推荐
[recommended by bloggers] C MVC list realizes the function of adding, deleting, modifying, checking, importing and exporting curves (with source code)
Discriminant model: a discriminant model creation framework log linear model
Mysql26 use of performance analysis tools
MySQL完全卸载(Windows、Mac、Linux)
Csdn-nlp: difficulty level classification of blog posts based on skill tree and weak supervised learning (I)
[C language] deeply analyze the underlying principle of data storage
Postman Interface Association
CSDN问答标签技能树(一) —— 基本框架的构建
Solve the problem that XML, YML and properties file configurations cannot be scanned
[recommended by bloggers] C # generate a good-looking QR code (with source code)
csdn-Markdown编辑器
C language string function summary
MySQL35-主从复制
MySQL transaction log
Mysql32 lock
MySQL completely uninstalled (windows, MAC, Linux)
Just remember Balabala
解决:log4j:WARN Please initialize the log4j system properly.
1. Mx6u learning notes (VII): bare metal development (4) -- master frequency and clock configuration
February 13, 2022-3-middle order traversal of binary tree