事务:
Transaction 其实指的一组操作,里面包含许多个单一的逻辑。只要有一个逻辑没有执行成功,那么都算失败。所有的数据都回归到最初的状态(回滚)
作用:为了确保逻辑的成功。例子:银行的转账
使用命令行方式演示事务:
开启事务
start transaction;
提交或者回滚事务
commit;提交事务,数据将会写到磁盘上的数据库
rollback;数据回滚,回到最初的状态
使用代码方式演示事务:
1.通过conn.setAutoCommit(false)来关闭自动提交的设置
2.提交事务 conn.commit();
3.回滚事务 conn.rollback();
事务的特性:
原子性、一致性、隔离性、持久性
按效率划分,从高到低:
读未提交 > 读已提交 >可重复读 > 可串行化
按拦截程度,从高到底:
可串行化 > 可重复读 > 读已提交 > 读未提交
事务总结:
1.在代码里面会使用事务
2.事务只是针对连接连接对象,如果再开一个连接对象,那么那是默认的提交
3.事务是会自动提交的
解决丢失更新:
悲观锁:可以在查询的时候,加入for update
乐观锁:要求程序员自己控制
数据库连接池:
1.数据库的连接对象创建工作,比较消耗性能
2.一开始先在内存中开辟一块空间(集合),一开始先往池子里面放置多个连接对象。后面需要连接的话,直接从池子里面去取。不要去自己创建连接了。使用完毕,要记得归还连接。确保连接对象能循环利用。
解决自定义数据库连接池出现的问题:
1.由于多了一个addBack方法,所以使用这个连接池的地方,需要额外记住这个方法,并且还不能面向接口编程
2.我们打算修改接口中的那个close方法,原来的Connection对象的Close方法,是真的关闭连接。
3.打算修改这个close方法,以后在调用close,并不是真的关闭,而是归还连接对象。
如何扩展某一个方法?
1.直接改源码 无法实现
2.继承,必须得知道这个接口的具体实现是谁
3.使用装饰者模式
4.动态代理
DBCP:
1.导入jar文件
2.不使用配置文件方式:
package com.itheima.dbcp;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.apache.commons.dbcp.BasicDataSource;
import org.junit.Test;
import com.itheima.util.JDBCUtil;
public class DBCPDemo {
@Test
public void testDBCP01() {
Connection conn=null;
PreparedStatement ps=null;
try {
//1.构建数据源对象
BasicDataSource dataSource = new BasicDataSource();
//连的是什么类型的数据库,访问的是哪个数据库,用户名,密码
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost/stus");
dataSource.setUsername("root");
dataSource.setPassword("root");
//2.得到连接对象
conn = dataSource.getConnection();
String sql = "insert into t_user values(null,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "admin");
ps.setString(2, "333");
ps.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtil.release(conn, ps);
}
}
}
2.使用配置文件方式:
package com.itheima.dbcp;
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
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;
import com.itheima.util.JDBCUtil;
public class DBCPDemo02 {
@Test
public void testDBCP02() {
/*BasicDataSource dataSource = new BasicDataSource();
dataSource.setConnectionProperties("dbcpconfig.properties");*/
Connection conn=null;
PreparedStatement ps=null;
try {
BasicDataSourceFactory factory = new BasicDataSourceFactory();
Properties properties = new Properties();
InputStream is = new FileInputStream("src//dbcpconfig.properties");
properties.load(is);
DataSource dataSource=factory.createDataSource(properties);
//2.得到连接对象
conn = dataSource.getConnection();
String sql = "insert into t_user values(null,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "hmx");
ps.setString(2, "123");
ps.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtil.release(conn, ps);
}
}
}
C3P0:
1.导入jar文件
2.不使用配置文件方式:
package com.itheima.c3p0;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.junit.Test;
import com.itheima.util.JDBCUtil;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Demo {
@Test
public void testC3P0() {
Connection conn = null;
PreparedStatement ps = null;
try {
//1.创建datasource
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//2.设置连接数据的信息
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost/stus");
dataSource.setUser("root");
dataSource.setPassword("root");
//2.得到连接对象
conn = dataSource.getConnection();
String sql = "insert into t_user values(null,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "admin");
ps.setString(2, "12333");
ps.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtil.release(conn, ps);
}
}
}
2.使用配置文件方式:c3p0-config.xml
package com.itheima.c3p0;
import java.sql.Connection;
import java.sql.PreparedStatement;
import org.junit.Test;
import com.itheima.util.JDBCUtil;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Demo02 {
@Test
public void testC3p0() {
Connection conn = null;
PreparedStatement ps = null;
try {
//
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//2.得到连接对象
conn = dataSource.getConnection();
String sql = "insert into t_user values(null,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "admin");
ps.setString(2, "1233333");
ps.executeUpdate() ;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtil.release(conn, ps);
}
}
}
<?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/stus</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>
</c3p0-config>
DBUtils:
package com.itheima.dbutils;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;
import com.itheima.domain.Account;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class TestDBUtils {
@Test
public void testInsert() throws SQLException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//dbutils只是帮我们简化了CRUD的代码,但是连接的创建以及获取工作,不在他的考虑范围
QueryRunner queryRunner = new QueryRunner(dataSource);
//针对增加、删除、修改
//queryRunner.update(sql);
//针对查询
//queryRunner.query(sql, rsh);
//queryRunner.update("insert into t_user values (null,?,?)", "HMX","111");
//queryRunner.update("delete from t_user where id = ?", 5);
//queryRunner.update("update t_user set password = ? where id = ?","Hmx",6);
//去执行查询,查询到的数据还是在那个result里面,然后调用下面的handle方法,由用户手动封装
/*Account account = queryRunner.query("select * from t_user where id = ?", new ResultSetHandler<Account>() {
@Override
public Account handle(ResultSet rs) throws SQLException {
Account account = new Account();
while(rs.next()) {
String name = rs.getString("username");
String password = rs.getString("password");
account.setName(name);
account.setPassword(password);
}
return account;
}
}, 6);
System.out.println(account.toString());*/
//通过类的字节码得到该类的实例
//Account a = new Account();
//创建一个类的实例
//Account a1 = Account.class.newInstance();
//Account account=queryRunner.query("select * from t_user where id = ?", new BeanHandler<Account>(Account.class), 3);
//System.out.println(account.toString());
List<Account> query = queryRunner.query("select * from t_user", new BeanListHandler<Account>(Account.class));
for (Account account : query) {
System.out.println(account.toString());
}
}
}
ResultSetHandler常用的实现类:
BeanHandler,查询到的单个数据封装成一个对象
BeanListHandler,查询到的多个数据封装成一个List<对象>
ArrayHandler
ArrayListHandler
MapHandler
MapListHandler