1.什么是事务
事务(Transaction),一般指要做的或所做的事情
在计算机术语中是指访问并可能更新数据库中的各种数据项的一个程序执行单元(unit)
程序执行单元(unit)--数据库操作的一组SQL语句的执行
1.由高级数据库操纵语言或编程语言(如:SQL、C++、Java)书写
2.由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成
例如:我们要实现一个银行转账的操作,首先要从A账户减掉金额,然后给B账户增加指定金额,此时转账操作结束。上面的操作如果对应城数据库在操作,那么就需要执行两条update语句。数据库把这两条update语句的执行就是一个事务
事务---指访问并可能更新数据库中各种数据项的一组SQL语句的执行单元(unit)
2. 数据库的事务有4大特征【ACID】
A---原子性(atomicity),一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做
C---一致性(consistency),事务必须是是数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的
I---隔离性(isolation),一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并执行的各个事务之间不能互相干扰
D--持久性(durability),持久性也称永久性,指一个事物一顿提交,他对数据库中的数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
3.Java中事务的隔离级别
在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别
JDBC定义了五种事务隔离级别:
TRANSACTION_READ_UNCOMMITTED 允许脏读、不可重复读或幻读
TRANSACTION_ READ_COMMITTED 禁止脏读,但是允许不可重复读和幻读
TRANSACTION_REPEATABLE-READ 禁止脏读和不可重复读,单运行可以幻读
TRANSACTION_SERIALIZABIE 禁止脏读、不可重复读和幻读
TRANSACTION_NONE JDBC 驱动不支持事务

4. 事务并发性带来的问题
在典型的应用程序中,多个事物并发运行,经常操作相同的数据来完成各自的任务(多个用户对同一数据进行操作)。并发虽然是必须的,但可能会导致以下问题。
1.脏读(Dirty read):当一个事务正在访问数据并且对数据进行了修改,而这种数据还没有提交到数据库时,这时另一个事务也访问了这个数据,并且使用了这个数据,因为这个数据时还没有提交的数据,另一个事务读到的这个数据时"脏数据",依据"脏数据"素偶走的操作可能不是正确的
2.丢失修改(Lost to modify):指在一个事务读取一个数据时,另一个事物也访问了该数据,那么在第一个事务修改了这个数据后,第二个事务也修改了这个数据,再这样一个事务内修改数据就被丢失,因此称为丢失修改,例如:事务1读取表中的数据A=20,事务2页读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失了
3.不可重复读(Unrepeatableread):指在一个事务内多次读取同一个数据,在这个事务还没结束时,第二个事务修改了该数据,那么,在第一个数据中两次读取数据之间,由于第二个事物的修改导致第一个事务两次读取的数据不一样的情况,因此称为不可重复读
4.幻读(Phantom read):幻读与不可重复读类似,它发生在第一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时,在随后的查询中,第一个事物(T1)就会发现多一个原本不存的记录,就好像发生幻觉一样,所以称为幻读。
不可重复读和幻读区别:
不可重复读重点在于修改,而幻读终点在于新增或删除
例1(同样的条件,你读取过的数据,再次读取出来发现值不一样):事务1中A先生读取自己的工资为1000的操作还没完成,事务2中的B先生修改了A先生的工资为2000,导致再读自己工资是变为2000,这就是不可重复读
例2(同样的条件,第一次和第二次读取出来的记录数不一样):假某工资单表中工资大于3000的有4人,事务1读取到所有工资大于3000的人,共查到4条记录,这是事务2有插入了一条工资大于3000的人,事务1再次读取时查到的记录变为5条,这样就导致了幻读
5.JDBC的事务管理操作
JDBC的事务管理操作需要通过java.sql.Connection接口来设置的
1.事务隔离级别:
| static int | TRANSACTION_NONE 指示不支持事务的常量。 |
| static int | TRANSACTION_READ_COMMITTED 一个常数表示防止脏读; 可能会发生不可重复的读取和幻像读取。 |
| static int | TRANSACTION_READ_UNCOMMITTED 一个常量表示可能会发生脏读,不可重复读和幻读。 |
| static int | TRANSACTION_REPEATABLE_READ 一个常量表示防止了脏读和不可重复读; 可以发生幻读。 |
| static int | TRANSACTION_SERIALIZABLE 一个常数表示防止脏读,不可重复读和幻影读。 |
| Modifier and Type | Constant Field | Value |
| public static final int | 0 | |
| public static final int | 2 | |
| public static final int | 1 | |
| public static final int | 4 | |
| public static final int | 8 |
2. 设置事务隔离级别的方法
void setTransactionIsolation(int level) 尝试将此 Connection对象的事务隔离级别更改为给定的对象。
例如:
Connection 接口对象. setTransactionIsolation (Connection.);
Connection接口对象.setTransactionIsolation(8);
设置是否自动提交事务方法【默认JDBC事务是自动提交的】
void setAutoCommit(boolean autoCommit) 将此连接的自动提交模式设置为给定状态。
void setAutoCommit(false)---设置手动提交事务
3.事务提交方法
void commit()---使自上次提交/回滚以来所做的所有更改都将永久性,并释放此Connection对象当前持有的任何数据库锁
4.事务回滚方法【异常执行】
void rollback()---撤销在当前事务中所作的所有更改,并释放Connection对象当前持有的任何数据库锁
create table t_user(
user_id int primary key auto_increment,
user_name varchar(20),
user_money int
);
insert into t_zhanghu values(null,'zhangsan',10000);
insert into t_zhanghu values(null,'lisi',10000);
package com.wangxing.test1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DBConnection {
//创建数据库启动名称
private static final String DRIVERNAME="com.mysql.jdbc.Driver";
//定义数据库的url
private static final String URL="jdbc:mysql://127.0.0.1:3306/bank";
//定义数据库的账号
private static final String USERNAME="root";
//定义数据库的密码
private static final String PASSWORD="123456";
//静态代码块
static{
//加载数据库驱动
try {
Class.forName(DRIVERNAME);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//得到数据库连接
public static Connection getConnection(){
Connection conn=null;
try {
conn=DriverManager.getConnection(URL, USERNAME, PASSWORD);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
}
package com.wangxing.test1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.PseudoColumnUsage;
import java.sql.SQLException;
import javax.swing.text.html.HTMLDocument.HTMLReader.PreAction;
/*
*
*/
public class BankClass {
public void zhanghu(String name,String name2,int jine){
Connection conn=DBConnection.getConnection();
PreparedStatement preparedStatement=null;
try {
//设置为手动提交事务
conn.setAutoCommit(false);
String sql="update t_user set user_money=? where user_name=?;";
preparedStatement=conn.prepareStatement(sql);
preparedStatement.setInt(1, 10000-1000);
preparedStatement.setString(2, "张三");
preparedStatement.executeUpdate();
preparedStatement.setInt(1, 10000+1000);
preparedStatement.setString(2, "李四");
preparedStatement.executeUpdate();
//提交事务
conn.commit();
} catch (Exception e) {
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
}finally{
try {
preparedStatement.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package com.wangxing.test1;
public class Test {
public static void main(String[] args) {
BankClass bc=new BankClass();
bc.zhanghu("张三","李四",10000);
}
}
总结:
1.SQL语句执行的connection与事务设置的connection对象要相同。
2.开始事务conn.setAutoCommit(false);
3.设置事务的隔离级别
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
4.提交事务conn.commit();
5.设置事务回滚【异常中进行】conn.rollback();
上面我们所操作的事务管理是编码式事务管理,后面我们在学习Spring框架的时候会学习到声明式事务管理。
6.通过JDBC使用DBCP与C3P0连接池操作
1.通过JDBC使用C3P0连接池
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。
例如:
1.创建数据库表
create table t_user(
stuid int primary key auto_increment,
stuname varchar(20),
stuage int,
stuaddress varchar(30)
);
2.创建Java项目,导入依赖包
c3p0-0.9.5.2.jar
mchange-commons-java-0.2.15.jar
mysql-connector-java-5.1.38.jar
3.在src下创建c3p0的配置文件【c3p0-config.xml】
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- c3p0的默认配置项 -->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/t_student</property>
<property name="user">root</property>
<property name="password">123456</property>
<!--c3p0数据库接池的初始容量 -->
<property name="initialPoolSize">5</property>
<!-- c3p0数据库连接池最大容量 -->
<property name="maxPoolSize">20</property>
</default-config>
<!-- 定义数据库配置 -->
<name-config name="t_student">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcURL">jdbc:mysql://127.0.0.1:3306/t_student</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="initialPoolSize">25</property>
<property name="MaxPoolSize">200</property>
</name-config>
</c3p0-config>
4. 创建Student
package com.wangxing.test1;
public class Student {
private int stuid;
private String stuname;
private int stuage;
private String stuaddress;
public int getStuid() {
return stuid;
}
public void setStuid(int stuid) {
this.stuid = stuid;
}
public String getStuname() {
return stuname;
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public int getStuage() {
return stuage;
}
public void setStuage(int stuage) {
this.stuage = stuage;
}
public String getStuaddress() {
return stuaddress;
}
public void setStuaddress(String stuaddress) {
this.stuaddress = stuaddress;
}
}
5. 创建数据库访问类
package com.wangxing.test1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class StudentDao {
public ComboPooledDataSource dataSource=null;
public StudentDao(){
//加载c3p0-config.xml文件中默认的config
//初始化数据源
dataSource =new ComboPooledDataSource();
//dataSource =new ComboPooledDataSource("t_student");
}
/*
* 根据id添加学生信息
*/
public boolean insertStudent(Student student){
boolean flag=false;
try {
Connection conn=dataSource.getConnection();
String sql2="insert into t_user values(null,?,?,?)";
PreparedStatement ps =conn.prepareStatement(sql2);
ps.setString(1, student.getStuname());
ps.setInt(2, student.getStuage());
ps.setString(3, student.getStuaddress());
int temp=ps.executeUpdate();
if(temp>0){
flag=true;
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return flag;
}
/*
* 根据id修改学生信息
*/
public boolean updateStudent(Student student){
boolean flag=false;
try {
Connection conn=dataSource.getConnection();
String sql3="update t_user set stuname=?,stuage=?,stuaddress=? where stuid";
PreparedStatement ps =conn.prepareStatement(sql3);
ps.setString(1, student.getStuname());
ps.setInt(2, student.getStuage());
ps.setString(3, student.getStuaddress());
int temp=ps.executeUpdate();
if(temp>0){
flag=true;
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return flag;
}
/*
* 根据id删除学生信息
*/
public boolean deleteStudent(int stuid){
boolean flag=false;
try {
Connection conn=dataSource.getConnection();
String sql4="delete from t_user where stuid=?";
PreparedStatement ps =conn.prepareStatement(sql4);
ps.setInt(1, stuid);
int temp=ps.executeUpdate();
if(temp>0){
flag=true;
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return flag;
}
/*
* 根据id查询学生信息
*/
public Student selectById(int stuid){
Student student=null;
try {
Connection conn=dataSource.getConnection();
String sql5="select*from t_user where stuid=?";
PreparedStatement ps =conn.prepareStatement(sql5);
ps.setInt(1, stuid);
ResultSet rs=ps.executeQuery();
if(rs.next()){
int userid=rs.getInt("stuid");
String username=rs.getString("stuname");
int userage=rs.getInt("stuage");
String useraddrss=rs.getString("stuaddress");
student=new Student();
student.setStuid(userid);
student.setStuname(username);
student.setStuage(userage);
student.setStuaddress(useraddrss);
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return student;
}
/*
* 查询全部学生信息
*/
public List<Student>selectAll(){
List<Student> studentlist=null;
try {
Connection conn=dataSource.getConnection();
String sql6="select*from t_user";
PreparedStatement ps =conn.prepareStatement(sql6);
ResultSet rs=ps.executeQuery();
studentlist=new ArrayList<Student>();
if(rs.next()){
int userid=rs.getInt("stuid");
String username=rs.getString("stuname");
int userage=rs.getInt("stuage");
String useraddrss=rs.getString("stuaddress");
Student student=new Student();
student.setStuid(userid);
student.setStuname(username);
student.setStuage(userage);
student.setStuaddress(useraddrss);
studentlist.add(student);
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return studentlist;
}
}
6.创建测试类
package com.wangxing.test1;
import java.util.List;
public class test1 {
public static void main(String[] args) {
StudentDao sdao=new StudentDao();
Student stu=new Student();
//添加学生信息
/*
stu.setStuname("张三");
stu.setStuage(23);
stu.setStuaddress("西安");
boolean f=sdao.insertStudent(stu);
if(f){
System.out.println("数据添加成功");
}
*/
//根据id修改学生信息
/*
stu.setStuname("李四");
stu.setStuage(28);
stu.setStuaddress("北京");
boolean f=sdao.updateStudent(stu);
if(f){
System.out.println("数据修改成功");
}
*/
//根据id删除学生信息
/*
boolean f=sdao.deleteStudent(2);
if(f){
System.out.println("数据删除成功");
}
*/
//根据id查询学深信息
/*
Student student=sdao.selectById(3);
if(student!=null){
System.out.println(student.getStuname()+"\t"+student.getStuage()+"\t"+student.getStuaddress());
}
*/
//查询全部学生信息
List<Student> studentlist=sdao.selectAll();
for(Student student:studentlist){
System.out.println(student.getStuname()+"\t"+student.getStuage()+"\t"+student.getStuaddress());
}
}
}
优点:不用手动编写创建数据库连接对象的操作,因为c3p0的数据库连接池的配置中已经配置初始化成功。提高程序的执行效率。 日后切换数据库的时候不需要修改源代码,只需要修改c3p0的数据库连接池的配置。
7. 通过JDBC使用dbcp连接池
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
实例:
1.创建数据库表
create table t_user(
stuid int primary key auto_increment,
stuname varchar(20),
stuage int,
stuaddress varchar(30)
);
3.创建java项目,导入jar包
commons-dbcp-1.4.jar
commons-dbutils-1.6.jar
commons-pool-1.6.jar
4.在src下创建数据库连接配置文件【xxxxxxxx.properties】
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/t_student?useUnicode=true&characterEncoding=utf8
username=root
password=123456
maxActive=50
maxIdle=20
maxWait=60000
4.创建Student
package com.wangxing.test1;
public class Student {
private int stuid;
private String stuname;
private int stuage;
private String stuaddress;
public int getStuid() {
return stuid;
}
public void setStuid(int stuid) {
this.stuid = stuid;
}
public String getStuname() {
return stuname;
}
public void setStuname(String stuname) {
this.stuname = stuname;
}
public int getStuage() {
return stuage;
}
public void setStuage(int stuage) {
this.stuage = stuage;
}
public String getStuaddress() {
return stuaddress;
}
public void setStuaddress(String stuaddress) {
this.stuaddress = stuaddress;
}
}
5.创建数据库访问类
package com.wangxing.test1;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
public class StudentDao {
public DataSource dataSource=null;
public StudentDao(){
try{
Properties pro=new Properties();
//创建输入流 this.getClass-得到当前类的反射对象,getResourceAsStream()--读取资源作为一个流
//从当前工程的src下寻找名字为mydata.properties的文件并作为输入流
InputStream inStream=this.getClass().getResourceAsStream("mydata.properties");
//加载读取文件的输入流
pro.load(inStream);
dataSource=BasicDataSourceFactory.createDataSource(pro);
}catch(Exception e){
e.printStackTrace();
}
}
/*
* 根据id添加学生信息
*/
public boolean insertStudent(Student student){
boolean flag=false;
try {
Connection conn=dataSource.getConnection();
String sql2="insert into t_user values(null,?,?,?)";
PreparedStatement ps =conn.prepareStatement(sql2);
ps.setString(1, student.getStuname());
ps.setInt(2, student.getStuage());
ps.setString(3, student.getStuaddress());
int temp=ps.executeUpdate();
if(temp>0){
flag=true;
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return flag;
}
/*
* 根据id修改学生信息
*/
public boolean updateStudent(Student student){
boolean flag=false;
try {
Connection conn=dataSource.getConnection();
String sql3="update t_user set stuname=?,stuage=?,stuaddress=? where stuid";
PreparedStatement ps =conn.prepareStatement(sql3);
ps.setString(1, student.getStuname());
ps.setInt(2, student.getStuage());
ps.setString(3, student.getStuaddress());
int temp=ps.executeUpdate();
if(temp>0){
flag=true;
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return flag;
}
/*
* 根据id删除学生信息
*/
public boolean deleteStudent(int stuid){
boolean flag=false;
try {
Connection conn=dataSource.getConnection();
String sql4="delete from t_user where stuid=?";
PreparedStatement ps =conn.prepareStatement(sql4);
ps.setInt(1, stuid);
int temp=ps.executeUpdate();
if(temp>0){
flag=true;
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return flag;
}
/*
* 根据id查询学生信息
*/
public Student selectById(int stuid){
Student student=null;
try {
Connection conn=dataSource.getConnection();
String sql5="select*from t_user where stuid=?";
PreparedStatement ps =conn.prepareStatement(sql5);
ps.setInt(1, stuid);
ResultSet rs=ps.executeQuery();
if(rs.next()){
int userid=rs.getInt("stuid");
String username=rs.getString("stuname");
int userage=rs.getInt("stuage");
String useraddrss=rs.getString("stuaddress");
student=new Student();
student.setStuid(userid);
student.setStuname(username);
student.setStuage(userage);
student.setStuaddress(useraddrss);
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return student;
}
/*
* 查询全部学生信息
*/
public List<Student>selectAll(){
List<Student> studentlist=null;
try {
Connection conn=dataSource.getConnection();
String sql6="select*from t_user";
PreparedStatement ps =conn.prepareStatement(sql6);
ResultSet rs=ps.executeQuery();
studentlist=new ArrayList<Student>();
if(rs.next()){
int userid=rs.getInt("stuid");
String username=rs.getString("stuname");
int userage=rs.getInt("stuage");
String useraddrss=rs.getString("stuaddress");
Student student=new Student();
student.setStuid(userid);
student.setStuname(username);
student.setStuage(userage);
student.setStuaddress(useraddrss);
studentlist.add(student);
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return studentlist;
}
}
6.创建测试类
package com.wangxing.test1;
import java.util.List;
public class test1 {
public static void main(String[] args) {
StudentDao sdao=new StudentDao();
Student stu=new Student();
//添加学生信息
/*
stu.setStuname("张三");
stu.setStuage(23);
stu.setStuaddress("西安");
boolean f=sdao.insertStudent(stu);
if(f){
System.out.println("数据添加成功");
}
*/
//根据修改学生信息
/*
stu.setStuname("李四");
stu.setStuage(28);
stu.setStuaddress("北京");
boolean f=sdao.updateStudent(stu);
if(f){
System.out.println("数据修改成功");
}
*/
//根据id删除学生信息
/*
boolean f=sdao.deleteStudent(2);
if(f){
System.out.println("数据删除成功");
}
*/
//根据id查询学深信息
/*
Student student=sdao.selectById(3);
if(student!=null){
System.out.println(student.getStuname()+"\t"+student.getStuage()+"\t"+student.getStuaddress());
}
*/
//查询全部学生信息
List<Student> studentlist=sdao.selectAll();
for(Student student:studentlist){
System.out.println(student.getStuname()+"\t"+student.getStuage()+"\t"+student.getStuaddress());
}
}
}
8. JDBC访问Druid
Druid首先是一个数据库连接池。Druid是目前最好的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池,包括DBCP、C3P0、BoneCP、Proxool、JBoss DataSource。Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。Druid是阿里巴巴开发的号称为监控而生的数据库连接池!
同时Druid不仅仅是一个数据库连接池,它包括四个部分:
1. Druid是一个JDBC组件,它包括三个部分:
基于Filter-Chain模式的插件体系。
DruidDataSource 高效可管理的数据库连接池。
SQLParser
2. Druid的功能
1、替换DBCP和C3P0。Druid提供了一个高效、功能强大、可扩展性好的数据库连接池。
2、可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。
3、数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDruiver和DruidDataSource都支持PasswordCallback。
4、SQL执行日志,Druid提供了不同的LogFilter,能够支持Common-Logging、Log4j和JdkLog,你可以按需要选择相应的LogFilter,监控你应用的数据库访问情况。
5、扩展JDBC,如果你要对JDBC层有编程的需求,可以通过Druid提供的Filter机制,很方便编写JDBC层的扩展插件。
所以Druid可以:
1、充当数据库连接池。
2、可以监控数据库访问性能
3、获得SQL执行日志
例如:
1.创建数据库表
2.创建java项目,导入jar包【druid-1.1.10.jar】
3.在src下创建数据库连接配置文件【xxxxxxxx.properties】
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/t_student?useUnicode=true&characterEncoding=utf8
username=root
password=123456
maxActive=50
maxIdle=20
maxWait=60000
Druid配置详解
Druid配置详解 https://blog.csdn.net/zhangjinwei417/article/details/92823438
4.创建Student
5.创建数据库访问类
package com.wangxing.test1;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.sql.DataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
public class StudentDao {
public DataSource dataSource=null;
public StudentDao(){
try{
Properties pro=new Properties();
//创建输入流 this.getClass-得到当前类的反射对象,getResourceAsStream()--读取资源作为一个流
//从当前工程的src下寻找名字为mydata.properties的文件并作为输入流
InputStream inStream=this.getClass().getResourceAsStream("mydata.properties");
//加载读取文件的输入流
pro.load(inStream);
dataSource=DruidDataSourceFactory.createDataSource(pro);
}catch(Exception e){
e.printStackTrace();
}
}
/*
* 根据id添加学生信息
*/
public boolean insertStudent(Student student){
boolean flag=false;
try {
Connection conn=dataSource.getConnection();
String sql2="insert into t_user values(null,?,?,?)";
PreparedStatement ps =conn.prepareStatement(sql2);
ps.setString(1, student.getStuname());
ps.setInt(2, student.getStuage());
ps.setString(3, student.getStuaddress());
int temp=ps.executeUpdate();
if(temp>0){
flag=true;
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return flag;
}
/*
* 根据id修改学生信息
*/
public boolean updateStudent(Student student){
boolean flag=false;
try {
Connection conn=dataSource.getConnection();
String sql3="update t_user set stuname=?,stuage=?,stuaddress=? where stuid";
PreparedStatement ps =conn.prepareStatement(sql3);
ps.setString(1, student.getStuname());
ps.setInt(2, student.getStuage());
ps.setString(3, student.getStuaddress());
int temp=ps.executeUpdate();
if(temp>0){
flag=true;
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return flag;
}
/*
* 根据id删除学生信息
*/
public boolean deleteStudent(int stuid){
boolean flag=false;
try {
Connection conn=dataSource.getConnection();
String sql4="delete from t_user where stuid=?";
PreparedStatement ps =conn.prepareStatement(sql4);
ps.setInt(1, stuid);
int temp=ps.executeUpdate();
if(temp>0){
flag=true;
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return flag;
}
/*
* 根据id查询学生信息
*/
public Student selectById(int stuid){
Student student=null;
try {
Connection conn=dataSource.getConnection();
String sql5="select*from t_user where stuid=?";
PreparedStatement ps =conn.prepareStatement(sql5);
ps.setInt(1, stuid);
ResultSet rs=ps.executeQuery();
if(rs.next()){
int userid=rs.getInt("stuid");
String username=rs.getString("stuname");
int userage=rs.getInt("stuage");
String useraddrss=rs.getString("stuaddress");
student=new Student();
student.setStuid(userid);
student.setStuname(username);
student.setStuage(userage);
student.setStuaddress(useraddrss);
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return student;
}
/*
* 查询全部学生信息
*/
public List<Student>selectAll(){
List<Student> studentlist=null;
try {
Connection conn=dataSource.getConnection();
String sql6="select*from t_user";
PreparedStatement ps =conn.prepareStatement(sql6);
ResultSet rs=ps.executeQuery();
studentlist=new ArrayList<Student>();
if(rs.next()){
int userid=rs.getInt("stuid");
String username=rs.getString("stuname");
int userage=rs.getInt("stuage");
String useraddrss=rs.getString("stuaddress");
Student student=new Student();
student.setStuid(userid);
student.setStuname(username);
student.setStuage(userage);
student.setStuaddress(useraddrss);
studentlist.add(student);
ps.close();
conn.close();
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return studentlist;
}
}
6.创建测试类
package com.wangxing.test1;
import java.util.List;
public class test1 {
public static void main(String[] args) {
StudentDao sdao=new StudentDao();
Student stu=new Student();
//添加学生信息
/*
stu.setStuname("张三");
stu.setStuage(23);
stu.setStuaddress("西安");
boolean f=sdao.insertStudent(stu);
if(f){
System.out.println("数据添加成功");
}
*/
//根据修改学生信息
/*
stu.setStuname("李四");
stu.setStuage(28);
stu.setStuaddress("北京");
boolean f=sdao.updateStudent(stu);
if(f){
System.out.println("数据修改成功");
}
*/
//根据id删除学生信息
/*
boolean f=sdao.deleteStudent(2);
if(f){
System.out.println("数据删除成功");
}
*/
//根据id查询学深信息
/*
Student student=sdao.selectById(3);
if(student!=null){
System.out.println(student.getStuname()+"\t"+student.getStuage()+"\t"+student.getStuaddress());
}
*/
//查询全部学生信息
List<Student> studentlist=sdao.selectAll();
for(Student student:studentlist){
System.out.println(student.getStuname()+"\t"+student.getStuage()+"\t"+student.getStuaddress());
}
}
}
本文介绍了数据库事务的定义,强调了其ACID特性,并详细讲解了Java JDBC中事务的隔离级别,包括脏读、不可重复读、幻读等问题。此外,还概述了JDBC事务管理操作,如设置事务隔离级别、手动提交和回滚事务。最后提到了通过JDBC使用DBCP、C3P0和Druid数据库连接池的操作。

598

被折叠的 条评论
为什么被折叠?



