Java全栈数据库技术:4.数据库之JDBC下
Posted new nm个对象
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java全栈数据库技术:4.数据库之JDBC下相关的知识,希望对你有一定的参考价值。
第四章 封装Druid
1.封装Druid
配置文件:src/druid.properties
#key=value
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=123456
initialSize=5
maxActive=10
maxWait=1000
JDBCTools工具类:
package com.atguigu.util;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
/*
* 获取连接或释放连接的工具类
*/
public class JDBCTools
// 1、数据源,即连接池
private static DataSource dataSource;
// 2、ThreadLocal对象
private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
static
try
//1、读取druip.properties文件
Properties pro = new Properties();
pro.load(JDBCTools2.class.getClassLoader().getResourceAsStream("druid.properties"));
//2、创建数据连接池
// DruidDataSourceFactory.createDataSource(Properties properties): 可以根据Properties对象来生成一个DataSource连接池对象
// 注意:这时Properties对象中的key不能随意更改,也就要求druid.properties配置文件中的key不能随意更改
dataSource = DruidDataSourceFactory.createDataSource(pro);
catch (Exception e)
e.printStackTrace();
/**
* 获取连接的方法
*
* @return
* @throws SQLException
*/
public static Connection getConnection()
// 从当前线程中获取连接
Connection connection = threadLocal.get();
if (connection == null)
// 从连接池中获取一个连接
try
connection = dataSource.getConnection();
// 将连接与当前线程绑定
// 执行完这行代码后,threadLocal.get()就会返回connection对象
threadLocal.set(connection);
catch (SQLException e)
e.printStackTrace();
return connection;
/**
* 释放连接的方法
*
* @param connection
*/
public static void releaseConnection()
// 获取当前线程中的连接
Connection connection = threadLocal.get();
if (connection != null)
try
connection.close();
catch (SQLException e)
e.printStackTrace();
finally
// 将已经关闭的连接从当前线程中移除
// 执行完这行代码后threadLocal.get()就会返回null
threadLocal.remove();
2.ThreadLocal:
JDK 1.2的版本中就提供java.lang.ThreadLocal,为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。通常用来在在多线程中管理共享数据库连接、Session等
ThreadLocal用于保存某个线程共享变量,原因是在Java中,每一个线程对象中都有一个ThreadLocalMap<ThreadLocal, Object>,其key就是一个ThreadLocal,而Object即为该线程的共享变量。而这个map是通过ThreadLocal的set和get方法操作的。对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。
1、ThreadLocal.get: 获取ThreadLocal中当前线程共享变量的值。
2、ThreadLocal.set: 设置ThreadLocal中当前线程共享变量的值。
3、ThreadLocal.remove: 移除ThreadLocal中当前线程共享变量的值。
3.测试一下
class Demo8 extends Thread
public static void main(String[] args) throws SQLException
for (int i = 0; i < 20; i++)
new Demo8().start();
@Override
public void run()
try
System.out.println("线程+"+this.getName()+"开始连接数据库");
// 获取连接
Connection connection = DruidTools.getConnection();
PreparedStatement preparedStatement = null;
// 生成命令发射器
preparedStatement = connection.prepareStatement("select * from employ3");
// 执行sql
ResultSet resultSet = preparedStatement.executeQuery();
// 处理结果
while (resultSet.next())
String name = resultSet.getString("ename");
String salary = resultSet.getString("salary");
System.out.println("姓名:"+name+"\\t薪资:"+salary);
// 释放连接
DruidTools.releaseConnection();
System.out.println("线程+"+this.getName()+"连接数据库结束");
catch (SQLException e)
e.printStackTrace();
第五章 更深层次的封装增删改查
前面我们对数据库的连接,资源的关闭进行了封装。实际上我们还可以进行更深层次的封装。将数据的增删改查封装为更加通用简洁的方法。
1.封装通用的增删改方法
package com.oy.jdbctest.jdbcutils;
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 java.util.ArrayList;
public class BasicDaoImpl
/*
* 通用的增、删、改的方法
*/
public int update(String sql,Object... args) throws SQLException
//1、获取链接对象
Connection conn = DruidTools.getConnection();
//2、编写sql,用形参传入的方式代替
//3、获取Statement或PreparedStatement对象
PreparedStatement pst = conn.prepareStatement(sql);
//设置?的值
//因为不知道sql中是否有?,以及?设置为什么值,通过形参来传入
//Object... args可变形参,可以传入0~n个值
//如果没有传入,说明没有?需要设置
//如果传入了n个值,那么说明sql中有n个?需要设置
if(args!=null && args.length>0)
for (int i = 0; i < args.length; i++)
//数组的下标从0开始,pst的?的序号是从1开始,所以这里用i+1
pst.setObject(i+1, args[i]);
//4、执行sql
int len = pst.executeUpdate();
//5、关闭
pst.close();
//这里不关闭conn,因为它在同一个事务的其他地方还要使用
return len;
/*
* 通用查询多个Javabean对象的方法
*/
public <T> ArrayList<T> getList(Class<T> clazz,String sql,Object... args) throws Exception
//1、获取链接对象
Connection conn = DruidTools.getConnection();
//2、编写sql,由形参传入
//3、获取PreparedStatement对象
PreparedStatement pst = conn.prepareStatement(sql);
//4、设置?,由形参传入
if(args!=null && args.length>0)
for (int i = 0; i < args.length; i++)
//数组的下标从0开始,pst的?的序号是从1开始,所以这里用i+1
pst.setObject(i+1, args[i]);
//5、执行sql
ResultSet rs = pst.executeQuery();
/*
* 如何把ResultSet结果集中的数据变成一个一个的Javabean对象,放到ArrayList对象,并且返回
*/
ArrayList<T> list = new ArrayList<>();
/*
* 要从ResultSet结果集中获取一共有几行,决定要创建几个对象
* 要从ResultSet结果集中获取一共有几列,决定要为几个属性赋值
* ResultSet结果集对象中,有一个方法ResultSetMetaData getMetaData()获取结果集的元数据
* 元数据就是描述结果集中的数据的数据,例如:列数,列名称等
*/
ResultSetMetaData metaData = rs.getMetaData();
int count = metaData.getColumnCount();//获取列数
while(rs.next())//循环一次代表一行,就要创建一个Javabean对象
//(1)创建一个Javabean对象
T t = clazz.newInstance();//这个方法有要求,要求Javabean这个类要有无参构造
//(2)设置对象的属性值
/*
* 反射操作属性的步骤:
* ①获取Class对象,现在有了
* ②获取属性对象Field
* Field f = clazz.getDeclaredField("属性名");
* ③创建Javabean对象,已经创建
* ④设置属性的可访问性 setAccessible(true)
* ⑤设置属性的值
*/
for (int i = 0; i < count; i++) //一共要为count个属性赋值
// Field f = clazz.getDeclaredField("属性名");
String fieldName = metaData.getColumnLabel(i+1);//获取第几列的字段名
Field f = clazz.getDeclaredField(fieldName);
f.setAccessible(true);
f.set(t, rs.getObject(i+1));//rs.getObject(i+1)获取第几列的值
//(3)把Javabean对象放到list中
list.add(t);
pst.close();
rs.close();
//这里不关闭conn,因为它在同一个事务的其他地方还要使用
return list;
protected <T> T getBean(Class<T> clazz,String sql,Object... args) throws Exception
return getList(clazz,sql,args).get(0);
练习:使用使用通用的增删改查方法实现Employee的增删改查
示例代码:EmployeeDAO.java
public interface EmployeeDAO
void addEmployee(Employee emp);
void updateEmployee(Employee emp);
void deleteByEid(int eid);
Employee getByEid(int eid);
ArrayList<Employee> getAll();
示例代码:EmployeeDAOImpl.java
package com.atguigu.test08.dao;
import java.sql.SQLException;
import java.util.ArrayList;
import com.atguigu.bean.Employee;
public class EmployeeDAOImpl extends BasicDAOImpl implements EmployeeDAO
@Override
public void addEmployee(Employee emp)
//`ename`,`tel`,`gender`,`salary`,`commission_pct`,`birthday`,
//`hiredate`,`job_id`,`email`,`mid`,`address`,`native_place`,`did`
String sql = "insert into t_employee values(null,?,?,?,?,?,?,?,?,?,?,?,?,?)";
try
update(sql, emp.getEname(),emp.getTel(),emp.getGender(),emp.getSalary(),emp.getCommissionPct(),
emp.getBirthday(),emp.getHiredate(),emp.getJobId(),emp.getEmail(),emp.getMid(),emp.getAddress(),
emp.getNativePlace(),emp.getDid());
catch (SQLException e)
throw new RuntimeException(e);
@Override
public void updateEmployee(Employee emp)
String sql = "update t_employee set `ename`=?,`tel`=?,`gender`=?,`salary`=?,`commission_pct`=?,`birthday`=?,`hiredate`=?,`job_id`=?,`email`=?,`mid`=?,`address`=?,`native_place`=?,`did`=? where eid=?";
try
update(sql, emp.getEname(),emp.getTel(),emp.getGender(),emp.getSalary(),emp.getCommissionPct(),
emp.getBirthday(),emp.getHiredate(),emp.getJobId(),emp.getEmail(),emp.getMid(),emp.getAddress(),
emp.getNativePlace(),emp.getDid(),emp.getEid());
catch (SQLException e)
throw new RuntimeException(e);
@Override
public void deleteByEid(int eid)
String sql = "delete from t_employee where eid=?";
try
update(sql, eid);
catch (SQLException e)
throw new RuntimeException(e);
@Override
public Employee getByEid(int eid)
//这里sql中通过取别名的方式,来指定对应的Javabean的属性名
String sql = "select `eid`,`ename`,`tel`,`gender`,`salary`,`commission_pct` commissionPct ,`birthday`,`hiredate`,`job_id` jobId,`email`,`mid`,`address`,`native_place` nativePlace,`did` from t_employee where eid=?";
Employee emp = null;
try
emp = getBean(Employee.class, sql, eid);
catch (Exception e)
throw new RuntimeException(e);
return emp;
@Override
public ArrayList<Employee> getAll()
//这里sql中通过取别名的方式,来指定对应的Javabean的属性名
String sql = "select `eid`,`ename`,`tel`,`gender`,`salary`,`commission_pct` commissionPct ,`birthday`,`hiredate`,`job_id` jobId,`email`,`mid`,`address`,`native_place` nativePlace,`did` from t_employee";
ArrayList<Employee> list = new ArrayList<Employee>();
try
list = getList(Employee.class, sql);
catch (Exception e)
throw new RuntimeException(e);
return list;
第六章 Apache的DBUtils
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
其中QueryRunner类封装了SQL的执行,是线程安全的。
(1)可以实现增、删、改、查、批处理、
(2)考虑了事务处理需要共用Connection。
(3)该类最主要的就是简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
(1)更新
public int update(Connection conn, String sql, Object… params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
…
(2)插入
public T insert(Connection conn,String sql,ResultSetHandler rsh, Object… params) throws SQLException:只支持INSERT语句,其中 rsh - The handler used to create the result object from the ResultSet of auto-generated keys. 返回值: An object generated by the handler.即自动生成的键值
…
(3)批处理
public int[] batch(Connection conn,String sql,Object[][] params)throws SQLException: INSERT, UPDATE, or DELETE语句
public T insertBatch(Connection conn,String sql,ResultSetHandler rsh,Object[][] params)throws SQLException:只支持INSERT语句
…
(4)使用QueryRunner类实现查询
public Object query(Connection conn, String sql, ResultSetHandler rsh,Object… params) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
…
***ResultSetHandler***接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet rs)该方法的返回值将作为QueryRunner类的query()方法的返回值。
该接口有如下实现类可以使用:
- BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
- BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
- ScalarHandler:查询单个值对象
- MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
- MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
- ColumnListHandler:将结果集中某一列的数据存放到List中。
- KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
- ArrayHandler:把结果集中的第一行数据转成对象数组。
- ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
示例代码:BasicDAOImpl.java
package com.atguigu.test09.dbutil;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
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.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import com.atguigu.util.JDBCTools;
//在这里都不关闭连接,统一关闭,因为Connection对象需要共享使用
public class BasicDAOImpl4
private QueryRunner qr =以上是关于Java全栈数据库技术:4.数据库之JDBC下的主要内容,如果未能解决你的问题,请参考以下文章