本文实例讲述了Hibernate JDBC实现批量插入、更新及删除的方法。分享给大家供大家参考,具体如下:
一、批量插入(两种方式)
1. 通过Hibernate缓存
如果这样写代码进行批量插入(初始设想):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package com.anlw.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import com.anlw.entity.Student;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
for ( int i = 0 ; i < 10 ; i++) {
Student s = new Student();
s.setAge(i + 1 );
s.setName( "test" );
sess.save(s);
}
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
如果数据量太大,会有可能出现内存溢出的异常;
小知识:
(1).Hibernate一级缓存,对其容量没有限制,强制使用,由于所有的对象都被保存到这个缓存中,内存总会达到一定数目时出现内存溢出的情况;
(2).Hibernate二级缓存可以进行大小配置;
要解决内存溢出的问题,就应该定时的将Sessiion缓存中的数据刷到数据库,正确的批量插入方式:
(1).设置批量尺寸(博主至今还没有明白下面这个属性和flush()方法的区别)
1
|
< property name = "hibernate.jdbc.batch_size" >2</ property >
|
配置这个参数的原因就是尽量少读数据库,该参数值越大,读数据库的次数越少,速度越快;上面这个配置,是Hibernate是等到程序积累了100个sql之后在批量提交;
(2).关闭二级缓存(这个博主也不是很明白)
1
|
< property name = "hibernate.cache.use_second_level_cache" >false</ property >
|
除了Session级别的一级缓存,Hibernate还有一个SessionFactory级别的二级缓存,如果启用了二级缓存,从机制上来说,Hibernate为了维护二级缓存,在批量插入时,hibernate会将对象纳入二级缓存,性能上就会有很大损失,也可能引发异常,因此最好关闭SessionFactory级别的二级缓存;
(3).在一二设置完成的基础上,清空Session级别的一级缓存;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
package com.anlw.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import com.anlw.entity.Student;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
for ( int i = 0 ; i < 10 ; i++) {
Student s = new Student();
s.setAge(i + 1 );
s.setName( "test" );
sess.save(s);
if (i% 100 == 0 ){ //以每100个数据作为一个处理单元
sess.flush(); //保持与数据库数据的同步
sess.clear(); //清楚Session级别的一级缓存的全部数据,及时释放占用的内存
}
}
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
2. 绕过Hibernate,直接调用JDBC API
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package com.anlw.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
//执行Work对象指定的操作,即调用Work对象的execute()方法
//Session会把当前使用的数据库连接传给execute()方法
sess.doWork( new Work() {
@Override
public void execute(Connection arg0) throws SQLException { //需要注意的是,不需要调用close()方法关闭这个连接
//通过JDBC API执行用于批量插入的sql语句
String sql = "insert into student(name,age) values(?,?)" ;
PreparedStatement ps = arg0.prepareStatement(sql);
for ( int i= 0 ;i< 10 ;i++){
ps.setString( 1 , "kobe" );
ps.setInt( 2 , 12 );
ps.addBatch();
}
ps.executeBatch();
}
});
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
注意:通过JDBC API中的PreparedStatement接口来执行sql语句,sql语句涉及到的数据不会被加载到Session的缓存中,因此不会占用内存空间,因此直接调用JDBC API批量化插入的效率要高于Hibernate缓存的批量插入;
更新&&删除
语法格式:(HQL)
update | delete from? <ClassName> [where where_conditions]
1>在from子句中,from关键字是可选的,即完全可以不写from关键字
2>在from子句中,只能有一个类名,可以在该类名后指定别名
3>不能在批量HQL语句中使用连接,显示或者隐式的都不行,但可以在where子句中使用子查询
4>整个where子句是可选的,where子句的语法sql语句中where子句的语法完全相同
5>Query.executeUpdate()方法返回一个整型值,该值是受此操作影响的记录数量,由于hibernate的底层操作实际上是由JDBC完成的,因此,如果有批量update或delete操作被转换成多条update或delete语句,(关联或者继承映射),该方法只能返回最后一条sql语句影响的记录行数,不是所有的记录行数,需要注意;
二、批量更新(两种方式)
1. 使用Hibernate直接进行批量更新
(1)方式1:(Hibernate的HQL直接支持update/delete的批量更新语法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
package com.anlw.util;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
//在HQL查询中使用update进行批量更新,下面的的语句是HQL语句,不是sql语句
Query query = sess.createQuery( "update Student set name = 'www'" );
query.executeUpdate();
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
(2)方式2:(强烈不推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
package com.anlw.util;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.hibernate.CacheMode;
import org.hibernate.Query;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import com.anlw.entity.Student;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
//查询表中的所有数据
ScrollableResults student = sess.createQuery( "from Student" )
.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
int count = 0 ;
while (student.next()){
Student s = (Student)student.get( 0 );
s.setName( "haha" );
if (++count% 3 == 0 ){
sess.flush();
sess.clear();
}
}
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
通过这种方式,虽然可以执行批量更新,但效果非常不好,执行效率不高,需要先执行数据查询,然后再执行数据更新,而且这种更新将是逐行更新,即每更新一行记录,都要执行一条update语句,性能非常低;
2. 绕过Hibernate,调用JDBC API
(1)方式1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package com.anlw.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
//执行Work对象指定的操作,即调用Work对象的execute()方法
//Session会把当前使用的数据库连接传给execute()方法
sess.doWork( new Work() {
@Override
public void execute(Connection arg0) throws SQLException { //需要注意的是,不需要调用close()方法关闭这个连接
String sql = "update student set name = 'oracle'" ;
//创建一个Satement对象
Statement st = arg0.createStatement();
//调用JDBC的update进行批量更新
st.executeUpdate(sql);
}
});
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
(2)方式2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package com.anlw.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
//执行Work对象指定的操作,即调用Work对象的execute()方法
//Session会把当前使用的数据库连接传给execute()方法
sess.doWork( new Work() {
@Override
public void execute(Connection arg0) throws SQLException { //需要注意的是,不需要调用close()方法关闭这个连接
String sql = "update student set name = ? where name=?" ;
PreparedStatement ps = arg0.prepareStatement(sql);
for ( int i= 0 ;i< 10 ;i++){
ps.setString( 1 , "tom" );
ps.setString( 2 , "oracle" );
ps.addBatch();
}
ps.executeBatch();
}
});
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
三、批量删除(两种方式)
1. 使用Hibernate直接进行批量删除
(1)方式1:(Hibernate的HQL直接支持update/delete的批量更新语法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
package com.anlw.util;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
//在HQL查询中使用delete进行批量删除,下面的的语句是HQL语句,不是sql
Query query = sess.createQuery( "delete Student" ); //也可以是delete from,from关键字是可选的,可以不要,加条件的时候可以指定类的别名
query.executeUpdate();
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
(2)方式2:(强烈不推荐)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
package com.anlw.util;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.hibernate.CacheMode;
import org.hibernate.Query;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import com.anlw.entity.Student;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
//查询表中的所有数据
ScrollableResults student = sess.createQuery( "from Student" )
.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
int count = 0 ;
while (student.next()){
Student s = (Student)student.get( 0 );
sess.delete(s);
}
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
通过这种方式,虽然可以执行批量删除,但效果非常不好,执行效率不高,需要先执行数据查询,然后再执行数据删除,而且这种删除将是逐行删除,即每删除一行记录,都要执行一条delete语句,性能非常低;
2. 绕过Hibernate,调用JDBC API
(1)方式1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package com.anlw.util;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import com.anlw.entity.Student;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
sess.doWork( new Work() {
@Override
public void execute(Connection arg0) throws SQLException {
String sql = "delete from student where age > 5" ; //mysql中删除语句不能省略from
Statement st = arg0.createStatement();
st.executeUpdate(sql);
}
});
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
2)方式2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
package com.anlw.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import com.anlw.entity.Student;
public class SessionUtil {
Configuration conf = null ;
ServiceRegistry st = null ;
SessionFactory sf = null ;
Session sess = null ;
Transaction tx = null ;
public void HIbernateTest() {
conf = new Configuration().configure();
st = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
sf = conf.buildSessionFactory(st);
try {
sess = sf.openSession();
tx = sess.beginTransaction();
sess.doWork( new Work() {
@Override
public void execute(Connection arg0) throws SQLException {
String sql = "delete from student where age = ?" ; //mysql中删除语句不能省略from
PreparedStatement ps = arg0.prepareStatement(sql);
for ( int i= 0 ;i< 10 ;i++){
if (i% 2 == 0 ){
ps.setInt( 1 , i);
ps.addBatch();
}
ps.executeBatch();
}
}
});
tx.commit();
} catch (Exception e) {
if (tx != null ) {
tx.rollback();
}
} finally {
sess.close();
sf.close();
}
}
public static void main(String[] args) {
new SessionUtil().HIbernateTest();
}
}
|
希望本文所述对大家基于Hibernate的java程序设计有所帮助。
原文链接:http://blog.csdn.net/an_2016/article/details/51759890