版权声明:如需转载或引用请声明原文网址 https://blog.csdn.net/u013087359/article/details/81814784
1.JDBC
1.1 入门例子
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try {
//1.加载mysql驱动
Class.forName("com.mysql.jdbc.Driver");
//2.根据数据库名、用户、密码创建连接对象
conn=DriverManager.getConnection("jdbc:mysql://localhost/test", "root", "root");
//3.获取操作sql语句的Statement对象
stmt=conn.createStatement();
//4.执行查询语句,返回结果集ResultSet
rs=stmt.executeQuery("select * from student");
//5.遍历结果集读取数据
while(rs.next()){
int id=rs.getInt("id");
String name=rs.getString("name");
int age=rs.getInt("age");
System.out.println("id="+id+",name="+name+",age="+age);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//关闭各种资源
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();
}
}
}
1.2 DBUtil简单封装
package com.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DBUtil {
private static Connection conn=null;
static{
try {
/*从配置文件中读取jdbc信息*/
Properties prop=new Properties();
//jdbc.properties存放在src下
prop.load(DBUtil.class.getClassLoader().getResourceAsStream("jdbc.properties"));
String driver=prop.getProperty("driver");
String url=prop.getProperty("url");
String user=prop.getProperty("user");
String password=prop.getProperty("password");
//加载驱动
Class.forName(driver);
//创建连接
conn=DriverManager.getConnection(url,user,password);
} catch (Exception e) {
e.printStackTrace();
}
}
//获取数据库连接对象
public static Connection getConnection(){
return conn;
}
//关闭资源
public static void close(Connection conn,Statement stmt,ResultSet rs){
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();
}
}
}
public static void close(Connection conn,Statement stmt){
close(conn,stmt,null);
}
}
1.3 PreparedStatement
PreparedStatement:对sql语句预编译,提高效率,而且可以防止sql注入
- 查询
Connection conn=null;
PreparedStatement pstmt=null;
ResultSet rs=null;
try {
conn=DBUtil.getConnection();
//使用?占位符代替变量
pstmt=conn.prepareStatement("select * from student where name=?");
//为占位符赋值,位置是从1算起
pstmt.setString(1, "张三");
rs= pstmt.executeQuery();
if(rs.next()){
String name=rs.getString("name");
int age=rs.getInt("age");
System.out.println("name="+name+",age="+age);
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtil.close(conn, pstmt,rs);
}
- 增删改
Connection conn=null;
PreparedStatement pstmt=null;
try {
conn=DBUtil.getConnection();
pstmt=conn.prepareStatement("insert into student values (null,?,?)");
pstmt.setString(1, "田七");
pstmt.setInt(2, 27);
//执行增删改操作,返回受影响的行数
int result=pstmt.executeUpdate();
if(result>0){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtil.close(conn, pstmt);
}
2.连接池
2.1 C3P0连接池
导入c3p0-0.9.1.2.jar包
在src下创建c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- 默认的连接池配置 -->
<default-config>
<!-- 数据库驱动 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<!-- 数据库连接字符串 -->
<property name="jdbcUrl">jdbc:mysql://localhost/test</property>
<!-- 数据库用户名 -->
<property name="user">root</property>
<!-- 数据库密码 -->
<property name="password">root</property>
<!-- 连接池的初始化的连接数量 -->
<property name="initialPoolSize">5</property>
<!-- 连接池最大的连接数 -->
<property name="maxPoolSize">20</property>
</default-config>
<!-- 带名字的连接池 -->
<named-config name="mypool">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost/test</property>
<property name="user">root</property>
<property name="password">root</property>
</named-config>
</c3p0-config>
- 连接池使用
//获取带名字的连接池
//DataSource ds=new ComboPooledDataSource("mypool");
//1.获取默认的连接池
DataSource ds=new ComboPooledDataSource();
Connection conn=null;
PreparedStatement pstmt=null;
ResultSet rs=null;
try {
//2.从连接池中获取连接
conn=ds.getConnection();
pstmt=conn.prepareStatement("select * from student where id=1");
rs=pstmt.executeQuery();
if(rs.next()) {
System.out.println("name="+rs.getString("name")+",age="+rs.getInt("age"));
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
//3.释放资源,连接会放回到连接池中,并不会直接关闭
//C3P0对Connection.close()进行了增强,这里因为多态实际使用的是增强类的close()
DBUtil.close(conn, pstmt, rs);
}
- C3P0简单封装
package com.util;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Util {
private static DataSource ds=new ComboPooledDataSource();
//获取数据源对象
public static DataSource getDataSource() {
return ds;
}
//从连接池中取出数据库连接
public static Connection getConnection() {
try {
return ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
2.2 DBCP连接池
- 导入commons-dbcp-1.4.jar和commons-pool-1.5.6.jar
- 在src下新建dbcp-config.properties
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost/test
username=root
password=root
#初始化连接
initialSize=10
#最大连接数量
maxActive=50
#最大空闲连接
maxIdle=20
#最小空闲连接
minIdle=5
#超时等待时间以毫秒为单位 6000毫秒/1000等于60秒
maxWait=60000
- dbcp简单工具类
package com.util;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
public class DBCPUtil {
private static DataSource ds = null;
static {
try {
Properties prop = new Properties();
//加载dbcp配置项进集合中
prop.load(DBCPUtil.class.getClassLoader().getResourceAsStream("dbcp-config.properties"));
//根据配置项集合创建连接池
ds = BasicDataSourceFactory.createDataSource(prop);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 获取数据源对象
public static DataSource getDataSource() {
return ds;
}
// 从连接池中取出数据库连接
public static Connection getConnection() {
try {
return ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
3. DBUtils
- 导入commons-dbutils-1.4.jar
- 例子
package com.test;
import java.sql.SQLException;
import java.util.List;
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.ScalarHandler;
import org.junit.Test;
import com.domain.Student;
import com.util.C3P0Util;
public class TestDBUtils {
@Test
public void testAdd() {
//根据数据源创建QueryRunner对象,会自动管理连接池的连接获取与回收
QueryRunner qr=new QueryRunner(C3P0Util.getDataSource());
//定义sql语句
String sql="insert into student values(null,?,?)";
//占位符填充的数据
Object[] params= {"小二",22};
try {
//进行增删改,返回受影响的行数
int rows=qr.update(sql, params);
if(rows>0) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
} catch (SQLException e) {
e.printStackTrace();
}
//不用手动释放数据库连接
}
@Test
public void testGetAll() {
try {
QueryRunner qr=new QueryRunner(C3P0Util.getDataSource());
//把所有记录集封装成对象集合
List<Student> students= qr.query("select * from student", new BeanListHandler<>(Student.class));
for (Student student : students) {
System.out.println(student);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void testGetOne() {
try {
QueryRunner qr=new QueryRunner(C3P0Util.getDataSource());
//把丢一行记录封装成单个对象
Student student= qr.query("select * from student where id=?", new BeanHandler<>(Student.class),1);
System.out.println(student);
} catch (SQLException e) {
e.printStackTrace();
}
}
@Test
public void testGetScalar() {
try {
QueryRunner qr=new QueryRunner(C3P0Util.getDataSource());
//返回记录的第一行第一列的单个数据
//count(*) 返回的是long类型
long count= (long)qr.query("select count(*) from student where age>?", new ScalarHandler(),24);
System.out.println(count);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
4. 事务处理
事务操作需要在同一个数据库连接上
4.1 JDBC方式
Connection conn=null;
try {
conn=DriverManager.getConnection(url, user, password);
//1.关闭事务的自动提交
conn.setAutoCommit(false);
// ... 执行相关的数据库操作
//2.正常运行提交事务
conn.commit();
//这里的异常要用Exception,任何异常都需要回滚事务
} catch (Exception e) {
if(conn!=null) {
try {
//3.出现异常回滚事务
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}finally {
// ...释放相关资源
}
4.2 DBUtils方式
Connection conn=null;
try {
conn=DataSourceUtils.getConnection();
//1.关闭事务的自动提交
conn.setAutoCommit(false);
//2.空参的QueryRunner创建对象,不要传递数据源
QueryRunner qr=new QueryRunner();
//3.update方法需要传递Connection对象
qr.update(conn,"update user set money=money-1000 where username='zhangsan'");
qr.update(conn,"update user set money=money+1000 where username='lisi'");
//4.事务提交
conn.commit();
} catch (Exception e) {
if(conn!=null) {
try {
//5.事务回滚
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
e.printStackTrace();
}finally {
DataSourceUtils.closeConnection(conn);
}
4.3 自定义封装类DataSourceUtils方式
package com.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DataSourceUtils {
//C3P0数据源
private static DataSource dataSource = new ComboPooledDataSource();
//本地线程的数据库连接,可以跨类跨方法访问同一个数据库连接(同一个线程内)
//以当前运行的线程作为Map的键,以Connection对象为值
private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
// 获取连接池
public static DataSource getDataSource() {
return dataSource;
}
// 从本地线程中获取连接对象
public static Connection getConnection() throws SQLException {
//从本地线程中获取连接对象,如果为null则从连接池中获取,并把连接对象放进本地线程中
Connection con = tl.get();
if (con == null) {
con = dataSource.getConnection();
tl.set(con);
}
return con;
}
// 开启事务
public static void startTransaction() throws SQLException {
Connection con = getConnection();
if (con != null) {
con.setAutoCommit(false);
}
}
// 事务回滚
public static void rollback() throws SQLException {
Connection con = getConnection();
if (con != null) {
con.rollback();
}
}
// 事务回滚并把连接对象归还连接池中
public static void rollbackAndClose() throws SQLException {
Connection con = getConnection();
if (con != null) {
try {
con.rollback(); // 回滚事务
} catch (SQLException e) {
e.printStackTrace();
}
con.close(); // 释放连接
tl.remove(); // 从本地线程绑定中移除
}
}
// 提交事务
public static void commit() throws SQLException {
Connection con = getConnection();
if (con != null) {
con.commit(); // 事务提交
}
}
// 提交事务并把连接对象归还连接池中
public static void commitAndClose() throws SQLException {
Connection con = getConnection();
if (con != null) {
try {
con.commit();// 事务提交
} catch (SQLException e) {
e.printStackTrace();
}
con.close(); // 释放连接
tl.remove(); // 从本地线程绑定中移除
}
}
//释放资源
public static void closeConnection(Connection conn) {
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void closeStatement(Statement stmt) {
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void closeResultSet(ResultSet rs) {
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(Connection conn,Statement stmt){
closeStatement(stmt);
closeConnection(conn);
}
public static void close(Connection conn,Statement stmt,ResultSet rs){
closeResultSet(rs);
closeStatement(stmt);
closeConnection(conn);
}
}
Connection conn=null;
try {
//1.获取连接对象
conn=DataSourceUtils.getConnection();
//2.开启事务
DataSourceUtils.startTransaction();
QueryRunner qr=new QueryRunner();
qr.update(conn,"update user set money=money-1000 where username='zhangsan'");
qr.update(conn,"update user set money=money+1000 where username='lisi'");
//3.提交事务并释放连接
DataSourceUtils.commitAndClose();
} catch (Exception e) {
e.printStackTrace();
try {
//4.回滚事务并释放连接
DataSourceUtils.rollbackAndClose();
} catch (SQLException e1) {
e1.printStackTrace();
}
}