1.先写一个简单的jdbc查询操作,了解思路:
package com.uwo9.testcrud;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
*
* JDBC查询操作
* @author Administrator
*
*/
public class TestQuery {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//2.获取连接
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger");
//3.创建SQL语句
String sql ="SELECT * FROM EMP";
//4.创建命令发送器对象
Statement stmt = conn.createStatement();
//5.发送SQL并且执行SQL语句
ResultSet rs = stmt.executeQuery(sql);
//6.遍历结果集
while(rs.next()){
System.out.println(rs.getInt(1)+"==="+rs.getString(2)+"==="+rs.getString(3));
}
//7.释放资源
rs.close();
stmt.close();
conn.close();
}
}
2.下面我们来封装jdbc util:
这里链接oracle数据库,
需要导入的包有:
ojdbc6.jar包(在oracle安装地址中可以找到,例如:D:\app\administrator\product\11.2.0\dbhome_1\jdbc\lib)
commons-beanutils-1.9.3.jar
commons-collections-3.2.2.jar
commons-logging-1.2.jar
包地址(链接:https://pan.baidu.com/s/1qXGvjxq 密码:7nfm)
先创建一个conn.properties文件,存放链接信息
driverName=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:orcl
uname =scott
pwd =tiger
再创建DBUtil.java文件
package com.uwo9.util;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
public class DBUtil {
private static String driverName = "";
private static String url = "";
private static String uname = "";
private static String pwd = "";
static {
try {
// Properties<String,String> extends HashTable<Object,Object>
// 1.创建Properties对象
Properties pro = new Properties();
// 2.加载properties文件
pro.load(DBUtil.class.getClassLoader().getResourceAsStream(
"conn.properties"));
// 3.读取properties文件中的数据
driverName = pro.getProperty("driverName");
url = pro.getProperty("url");
uname = pro.getProperty("uname");
pwd = pro.getProperty("pwd");
// 加载驱动
Class.forName(driverName);
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
*
* 获取连接
*
* @return
*/
public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(url, uname, pwd);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 获取Statement对象
*
* @param conn
* @return
*/
public static Statement getStatement(Connection conn) {
Statement stmt = null;
try {
stmt = conn.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
return stmt;
}
/**
* 获取预编译的命令发送
*
* @param conn
* @param sql
* @return
*/
public static PreparedStatement getPreparedStatement(Connection conn,
String sql) {
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return pstmt;
}
/**
* 释放资源
*
* @param rs
* @param stmt
* @param conn
*/
public static void closeAll(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 封装DML操作工具方法
*
* @param sql
* @param params
* @return
*/
public static boolean executeDML(String sql, Object... params) {
// 声明连接
Connection conn = null;
PreparedStatement pstmt = null;
try {
// 获取连接
conn = getConnection();
// 取消事务的自动提交
conn.setAutoCommit(false);
// 获取命令发送器
pstmt = DBUtil.getPreparedStatement(conn, sql);
// 给SQL参数赋值
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
// 发送SQL并执行SQL
int count = pstmt.executeUpdate();
// 判断
if (count == 0) {
// 手动回滚事务
conn.rollback();
return false;
} else {
// 手动提交事务
conn.commit();
return true;
}
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {// 释放资源
DBUtil.closeAll(null, pstmt, conn);
}
return false;
}
/**
* 封装查询操作的工具方法
*
* @param cls
* @param sql
* @param params
* @return
*/
public static <T> List<T> executeDQL(Class<T> cls, String sql,
Object... params) {
// 创建返回值对象
List<T> list = new ArrayList<T>();
// 声明连接
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 获取连接
conn = getConnection();
// 获取命令发送器
pstmt = getPreparedStatement(conn, sql);
// 给sql参数赋值
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
// 发送SQL并执行SQL
rs = pstmt.executeQuery();
// 获取结果集的元数据信息(列数,字段名称,总列数)
ResultSetMetaData metadata = rs.getMetaData();
// 遍历结果集
while (rs.next()) {
// 创建T对象
T obj = cls.newInstance();
// 获取结果集中的数据并且赋值给T对象
for (int i = 1; i <= metadata.getColumnCount(); i++) {
BeanUtils.setProperty(obj, metadata.getColumnLabel(i)
.toLowerCase(), rs.getObject(i));
}
ConvertUtils.register(new DateConverter(null),
java.util.Date.class);
// 将每条记录的对象存放至list集合中
list.add(obj);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} finally {// 关闭资源
closeAll(rs, pstmt, conn);
}
return list;
}
}
3.再次优化,使用连接池,使之链接更稳定,效率更高。
这里链接mysql数据库,
需要导入的包有:
mysql-connector-java-5.1.8-bin.jar包地址(链接:https://pan.baidu.com/s/1pK8VEVT 密码:f5gj)
commons-beanutils-1.9.3.jar
commons-collections-3.2.2.jar
commons-logging-1.2.jar
包地址(链接:https://pan.baidu.com/s/1qXGvjxq 密码:7nfm)
proxool-0.9.1.jar
proxool-cglib.jar
包地址(链接:https://pan.baidu.com/s/1pLkjoFL 密码:2rlv)
先创建一个proxool.properties文件,存放连接池信息
#连接池标识, 用于确定从何处获取数据库连接池
jdbc-1.proxool.alias=test
#连接数据库的驱动
jdbc-1.proxool.driver-class=com.mysql.jdbc.Driver
#连接数据库的url
jdbc-1.proxool.driver-url=jdbc:mysql://localhost:3306/testkaoshi?useUnicode=true&characterEncoding=utf8
#用户名
jdbc-1.user=root
#密码
jdbc-1.password=123456
#可以允许存在的最大连接数
jdbc-1.proxool.maximum-connection-count=50
#保持打开状态的最小连接数
jdbc-1.proxool.minimum-connection-count=5
#最少保持的空闲连接数(默认2个)
#连接池中可用的连接数量。如果当前的连接池中的连接少于这个数值,新的连接将被建立。
jdbc-1.proxool.prototype-count=4
#详细信息设置。 参数 boolean值
jdbc-1.proxool.verbose=true
#连接池使用状况统计。 参数"10s,1m,1d"
jdbc-1.proxool.statistics=10s,1m,1d
#日志统计跟踪类型。 参数"ERROR"或 "INFO"
jdbc-1.proxool.statistics-log-level=error
在WebRoot/WEB-INF/web.xml文件中添加
<!-- web中配置proxool,并自动加载 -->
<servlet>
<servlet-name>ServletConfigurator</servlet-name>
<servlet-class>
org.logicalcobwebs.proxool.configuration.ServletConfigurator
</servlet-class>
<init-param>
<param-name>propertyFile</param-name>
<param-value>WEB-INF/classes/proxool.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
再创建DBUtil.java文件
package com.libsys.util;
import java.lang.reflect.InvocationTargetException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.beanutils.converters.SqlTimestampConverter;
/**
* JDBC工具类
*
* @author Issac
*
*/
public class DBUtil {
/**
* 获取连接池的连接
*
* @return
*/
public static Connection getProxoolConnection() {
Connection conn = null;
try {
// 加载连接池驱动
Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
conn = DriverManager.getConnection("proxool.test");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**
* 获取Statement对象
*
* @param conn
* @return
*/
public static Statement getStatement(Connection conn) {
Statement stmt = null;
try {
stmt = conn.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
return stmt;
}
/**
* 获取预编译的命令发送
*
* @param conn
* @param sql
* @return
*/
public static PreparedStatement getPreparedStatement(Connection conn,
String sql) {
PreparedStatement pstmt = null;
try {
pstmt = conn.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
}
return pstmt;
}
/**
* 释放资源
*
* @param rs
* @param stmt
* @param conn
*/
public static void closeAll(ResultSet rs, Statement stmt, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 封装DML操作工具方法 增删改
*
* @param sql
* @param params
* @return
*/
public static boolean executeDML(String sql, Object... params) {
// 声明连接
Connection conn = null;
PreparedStatement pstmt = null;
try {
// 获取连接
conn = getProxoolConnection();
// 取消事务的自动提交
conn.setAutoCommit(false);
// 获取命令发送器
pstmt = DBUtil.getPreparedStatement(conn, sql);
// 给SQL参数赋值
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
// 发送SQL并执行SQL
int count = pstmt.executeUpdate();
// 判断
if (count == 0) {
// 手动回滚事务
conn.rollback();
return false;
} else {
// 手动提交事务
conn.commit();
return true;
}
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {// 释放资源
DBUtil.closeAll(null, pstmt, conn);
}
return false;
}
/**
* 封装DML批量操作工具方法 批量增删改
* 采用Statement.addBatch(sql)方式实现批处理:
* 优点:可以向数据库发送多条不同的SQL语句。
* 缺点:SQL语句没有预编译。
* 当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句。
* @param sqlList
* @return
*/
public static boolean executeDMLOfBatch(List<String>sqlList){
//声明连接
Connection conn=null;
Statement stmt=null;
try {
// 获取连接
conn = getProxoolConnection();
// 取消事务的自动提交
conn.setAutoCommit(false);
// 获取命令发送器
stmt = getStatement(conn);
for (String sql : sqlList) {
stmt.addBatch(sql);
}
boolean flag = true;
//执行批处理SQL语句
int[]counts= stmt.executeBatch();
isSucceed(conn,counts,flag);
//清楚批处理
stmt.clearBatch();
return flag;
} catch (SQLException e) {
e.printStackTrace();
}finally {// 释放资源
closeAll(null, stmt, conn);
}
return false;
}
/**
* 封装DML批量操作工具方法 批量增删改
* 采用PreparedStatement.addBatch()方式实现批处理的优缺点
* 优点:发送的是预编译后的SQL语句,执行效率高。
* 缺点:只能应用在SQL语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。
* @param sql
* @param params
* @return
*/
public static boolean executeDMLOfBatch(String sql, List<Object[]> list) {
// 声明连接
Connection conn = null;
PreparedStatement pstmt = null;
try {
// 获取连接
conn = getProxoolConnection();
// 取消事务的自动提交
conn.setAutoCommit(false);
// 获取命令发送器
pstmt = getPreparedStatement(conn, sql);
// 给SQL参数赋值
Object[] o = null;
boolean flag = true;
for (int i = 0; i < list.size() && flag; i++) {
o = list.get(i);
for (int j = 0; j < o.length; j++) {
pstmt.setObject(j + 1, o[j]);
}
pstmt.addBatch();
// 每500条执行一次,避免内存不够的情况,可参考,Eclipse设置JVM的内存参数
if (i > 0 && i % 500 == 0) {
int[] counts = pstmt.executeBatch();
isSucceed(conn,counts,flag);
pstmt.clearBatch();// 清除批处理命令
}
}
//执行最后剩下不够500条的
if(list.size()%500>0){
int[] countss = pstmt.executeBatch();// 发送SQL并执行SQL
isSucceed(conn,countss,flag);
}
pstmt.clearBatch();// 清除批处理命令
return flag;
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {// 释放资源
closeAll(null, pstmt, conn);
}
return false;
}
/**
* DML批量操作是否成功
* @param conn
* @param counts
* @param flag
* @throws SQLException
*/
private static void isSucceed(Connection conn,int[] counts,boolean flag) throws SQLException{
if (counts == null) {
// 手动回滚事务
conn.rollback();
flag = false;
} else {
for (int k = 0; k < counts.length && flag; k++) {
if (counts[k] == 0) {// 判断
flag = false;
}
}
if (flag) {
// 手动提交事务
conn.commit();//如果不想出错后,完全没保留数据,则可以没执行一次提交一次,但得保证数据不会重复
} else {
// 手动回滚事务
conn.rollback();
}
}
}
/**
* 封装查询操作的工具方法
*
* @param cls
* @param sql
* @param params
* @return
*/
public static <T> List<T> executeDQL(Class<T> cls, String sql,
Object... params) {
// 创建返回值对象
List<T> list = new ArrayList<T>();
// 声明连接
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 获取连接
conn = getProxoolConnection();
// 获取命令发送器
pstmt = getPreparedStatement(conn, sql);
// 给sql参数赋值
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
// 发送SQL并执行SQL
rs = pstmt.executeQuery();
// 获取结果集的元数据信息(列数,字段名称,总列数)
ResultSetMetaData metadata = rs.getMetaData();
// 遍历结果集
while (rs.next()) {
// 创建T对象
T obj = cls.newInstance();
// 获取结果集中的数据并且赋值给T对象
for (int i = 1; i <= metadata.getColumnCount(); i++) {
ConvertUtils.register(new DateConverter(null), java.util.Date.class);
BeanUtils.setProperty(obj, metadata.getColumnLabel(i)
.toLowerCase(), rs.getObject(i));
}
// 将每条记录的对象存放至list集合中
list.add(obj);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} finally {// 关闭资源
closeAll(rs, pstmt, conn);
}
return list;
}
/**
* 返回一个值
* @param sql
* @param params
* @return
*/
public static int executeDQLGetValue(String sql,Object... params) {
// 声明连接
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
// 获取连接
conn = getProxoolConnection();
// 获取命令发送器
pstmt = getPreparedStatement(conn, sql);
// 给sql参数赋值
for (int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
// 发送SQL并执行SQL
rs = pstmt.executeQuery();
// 遍历结果集
while (rs.next()) {
return rs.getInt(1);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {// 关闭资源
closeAll(rs, pstmt, conn);
}
return 0;
}
}