1.批处理:批量对数据库作增,删,改的操作。
批处理的优点:减少应用程序与数据库服务器交互次数,从而提高项目的运行性能。
2.批量执行多条sql语句,sql语句不相同,返回类型相同
eg:public static void main(String[] args) throws SQLException {
//声明连接对象,执行对象
Connection conn=null;
Statement state=null;
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.创建连接对象
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/studentmanager", "root", "123");
//3.准备Sql语句
String sql1="insert into t_student(sname,phone) values('cc','120')";
String sql2="update t_student set sname='cs',phone='110' where sname='cc'";
String sql3="delete from t_student where sname='cs'";
//4.创建执行对象
state=conn.createStatement();
//5.用执行对象调用相应的方法将Sql语句加入批处理
state.addBatch(sql1);
state.addBatch(sql2);
state.addBatch(sql3);
//6.用执行对象调用相应方法将批处理的Sql语句传到数据库中执行,并等到结果
int[] result=state.executeBatch();
//7.处理结果
for (int i : result) {
System.out.println(i);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//8.关对象
if (state!=null) {
state.close();
}
if (conn!=null) {
conn.close();
}
}
}
3.批量插入100条记录,sql语句相同,只是参数值不同
eg:public static void main(String[] args) throws SQLException {
//声明连接对象,执行对象
Connection conn=null;
PreparedStatement state=null;
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.创建连接对象
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/studentmanager", "root", "123");
//3.准备Sql语句
String sql1="insert into t_student(sname,phone) values(?,?)";
//4.创建执行对象
state=conn.prepareStatement(sql1);
//5.用执行对象调用相应的方法向sql语句的占位符传参,将参数添加到批处理中
for (int i = 1; i <=100; i++) {
state.setString(1, "a"+i);
state.setString(2, "11"+i);
//将参数添加到批处理中
state.addBatch();
}
//6.将批处理的数据传到数据库中去执行,并得到结果
int[] result=state.executeBatch();
//7.处理结果
for (int i : result) {
System.out.print(i+"\t");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//8.关对象
if (state!=null) {
state.close();
}
if (conn!=null) {
conn.close();
}
}
}
4.批量插入10000条记录,Sql语句相同,需要分批次提交
eg:public static void main(String[] args) throws SQLException {
//声明连接对象,执行对象
Connection conn=null;
PreparedStatement state=null;
//声明一个二维数组存结果
int[][] nums=new int[10][100];
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.创建连接对象
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/studentmanager", "root", "123");
//3.准备Sql语句
String sql1="insert into t_student(sname,phone) values(?,?)";
//4.创建执行对象
state=conn.prepareStatement(sql1);
//5.用执行对象调用相应的方法向sql语句的占位符传参,将参数添加到批处理中
for (int i = 1; i <=1000; i++) {
state.setString(1, "b"+i);
state.setString(2, "11"+i);
//将参数添加到批处理中
state.addBatch();
if (i%100==0) {
//6.将批处理的数据传到数据库中去执行,并得到结果
nums[i/100-1]=state.executeBatch();
//清空批处理原来的数据
state.clearBatch();
}
}
//7.处理结果
for (int[] is : nums) {
for (int is2 : is) {
System.out.print(is2+"\t");
}
System.out.println();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//8.关对象
if (state!=null) {
state.close();
}
if (conn!=null) {
conn.close();
}
}
}
5.事务:由一条或多条SQL语句组成执行单元,这个执行单元要么同时执行成功,要么同时执行失败。
作用:保证数据安全。
6.事务常用语法:同一个事务要用同一个连接对象。
数据库 Java程序
开启事务 start transaction 连接对象.setAutoCommit(false)
提交事务 commit; 连接对象.commit();
回滚事务 rollback; 连接对象.rollback();
eg:#开启事务
START TRANSACTION;
update t_bank set money=money-200 where acount=‘张三’;
update t_bank set money=money+200 where acount=‘李四’;
#回滚事务
ROLLBACK;
#提交事务
commit;
eg:public static void main(String[] args) throws SQLException {
//声明连接对象,执行对象
Connection conn=null;
Statement state=null;
//创建jdbc工具类的对象
BaseDAO bd=new BaseDAO();
//准备转账的Sql语句
String sql1="update t_bank set money=money-200 where acount='张三'";
String sql2="update t_bank set money=money+200 where acount='李四'";
try {
//获得连接对象
conn=bd.getConnection();
//通过连接对象创建执行对象
state=conn.createStatement();
//开启事务
conn.setAutoCommit(false);
//实现银行转账的业务
int result1=state.executeUpdate(sql1);
int num=8/0;
int result2=state.executeUpdate(sql2);
//处理结果
if (result1>0&&result2>0) {
//提交事务
conn.commit();
System.out.println("转账成功");
}else {
System.out.println("转账失败");
}
} catch (Exception e) {
//回滚事务
conn.rollback();
e.printStackTrace();
}finally {
//关闭对象
bd.closeObject2();
}
}
7.事务的特性:ACID
7.1:原子性(Atomicity ):事务是数据库的逻辑工作单位,事务中包含的各操作要么都完成,要么 都不完成
7.2:一致性(Consistency):事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性 状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状 态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些 未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处 于一种不正确的状态,或者说是 不一致的状态。
7.3:隔离性( Isolation):一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数 据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
7.4:持久性(Durability):指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。 接下来的其它操作或故障不应该对其执行结果有任何影响。
8.事务隔离的错误
8.1:脏读:一个线程中的事务读到了另外一个线程中未提交的数据。
8.2:不可重复读:一个线程中的事务读到了另外一个线程中已经提交的update的数据。
8.3:虚读:一个线程中的事务读到了另外一个线程中已经提交的insert的数据。
9.事务的级别:事务级别越高,安全性越高,效率越低。
9.1:READ UNCOMMITTED 脏读、不可重复读、虚读有可能发生。
9.2:READ COMMITTED 避免脏读的发生,不可重复读、虚读有可能发生。
9.3:REPEATABLE READ 避免脏读、不可重复读的发生,虚读有可能发生。
9.4:SERIALIZABLE 避免脏读、不可重复读、虚读的发生。
MySql:REPEATABLE READ Oracle:READ COMMITTED
10.设置事务的隔离:set [GLOBAL | SESSION] transaction isolation level 级别;
注意:设置完事务的隔离级别后,要重新连接数据库才能生效。
查看当前的隔离级别:select @@tx_isolation;
11.(扩展)存大数据:
11.1:存大文本:text,longtext
eg:public static void main(String[] args) {
/**
* 声明连接对象,执行对象,结果集对象
*/
Connection conn=null;
PreparedStatement state=null;
ResultSet rs=null;
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.创建连接对象
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool", "root", "123");
//3.准备Sql语句
String sql="insert into t_book(bookName,content) values(?,?)";
//4.创建执行对象
state=conn.prepareStatement(sql);
//创建存的文件对象
File f1=new File("aa/灵剑山.txt");
//用执行 对象调用相应的方法来给占位符传参
state.setString(1, f1.getName());
state.setCharacterStream(2, new FileReader(f1), (int)f1.length());
//5.用执行对象调用相应的方法将Sql语句传入数据库执行,并接收结果
int result=state.executeUpdate();
//6.处理结果
if (result>0) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//7.关对象
try {
if (rs!=null) {
rs.close();
}
if (state!=null) {
state.close();
}
if (conn!=null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
/**
* 声明连接对象,执行对象,结果集对象
*/
Connection conn=null;
PreparedStatement state=null;
ResultSet rs=null;
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.创建连接对象
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool", "root", "123");
//3.准备Sql语句
String sql="select bookName,content from t_book";
//4.创建执行对象
state=conn.prepareStatement(sql);
//5.用执行对象调用相应的方法将Sql语句传入数据库执行,并接收结果
rs=state.executeQuery();
//6.处理结果
while (rs.next()) {
String bookName=rs.getString("bookName");
Reader r=rs.getCharacterStream("content");
//创建一个写入流,将从数据库读取大文本文件写入到当前项目下
Writer w=new OutputStreamWriter(new FileOutputStream("bb/"+bookName), "utf-8");
//边读边写入
char[] c=new char[100];
int len=r.read(c);
while (len!=-1) {
//读一次写入一次
w.write(c, 0, len);
//接着读取
len=r.read(c);
}
r.close();
w.close();
}
System.out.println("读取完毕");
} catch (Exception e) {
e.printStackTrace();
}finally {
//7.关对象
try {
if (rs!=null) {
rs.close();
}
if (state!=null) {
state.close();
}
if (conn!=null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
11.2:存二进制数据数据:blob,longblob
eg:public static void main(String[] args) {
/**
* 声明连接对象,执行对象,结果集对象
*/
Connection conn=null;
PreparedStatement state=null;
ResultSet rs=null;
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.创建连接对象
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool", "root", "123");
//3.准备Sql语句
String sql="insert into t_file(fileName,content) values(?,?)";
//4.创建执行对象
state=conn.prepareStatement(sql);
//用执行对象调用相应的方法给占位符
File f2=new File("aa/2.jpg");
state.setString(1, f2.getName());
state.setBinaryStream(2, new FileInputStream(f2), (int)f2.length());
//5.用执行对象调用相应的方法将Sql语句传入数据库执行,并接收结果
int result=state.executeUpdate();
//6.处理结果
if (result>0) {
System.out.println("添加成功");
}else {
System.out.println("添加失败");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//7.关对象
try {
if (rs!=null) {
rs.close();
}
if (state!=null) {
state.close();
}
if (conn!=null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
/**
* 声明连接对象,执行对象,结果集对象
*/
Connection conn=null;
PreparedStatement state=null;
ResultSet rs=null;
try {
//1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//2.创建连接对象
conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/myschool", "root", "123");
//3.准备Sql语句
String sql="select fileName,content from t_file";
//4.创建执行对象
state=conn.prepareStatement(sql);
//5.用执行对象调用相应的方法将Sql语句传入数据库执行,并接收结果
rs=state.executeQuery();
//6.处理结果
while (rs.next()) {
String fileName=rs.getString("fileName");
InputStream is= rs.getBinaryStream("content");
//创建写入流,将从数据库读取二进制文件写入到当前项目中
OutputStream os=new FileOutputStream("bb/"+fileName);
//边读取边写入
byte[] b=new byte[1024];
int len=is.read(b);
while (len!=-1) {
//读取一次就写入一次
os.write(b, 0, len);
//接着读取
len=is.read(b);
}
is.close();
os.close();
}
System.out.println("读取成功");
} catch (Exception e) {
e.printStackTrace();
}finally {
//7.关对象
try {
if (rs!=null) {
rs.close();
}
if (state!=null) {
state.close();
}
if (conn!=null) {
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}