Hibernate+JDBC实现批量插入、更新及删除的方法详解

网友投稿 1607 2023-03-22


Hibernate+JDBC实现批量插入、更新及删除的方法详解

本文实例讲述了Hibernate JDBC实现批量插入、更新及删除的方法。分享给大家供大家参考,具体如下:

一、批量插入(两种方式)

1. 通过Hibernate缓存

如果这样写代码进行批量插入(初始设想):

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()方法的区别)

2

配置这个参数的原因就是尽量少读数据库,该参数值越大,读数据库的次数越少,速度越快;上面这个配置,是Hibernate是等到程序积累了100个sql之后在批量提交;

(2).关闭二级缓存(这个博主也不是很明白)

false

除了Session级别的一级缓存,Hibernate还有一个SessionFactory级别的二级缓存,如果启用了二级缓存,从机制上来说,Hibernate为了维护二级缓存,在批量插入时,hibernate会将对象纳入二级缓存,性能上就会有很大损失,也可能引发异常,因此最好关闭SessionFactory级别的二级缓存;

(3).在一二设置完成的基础上,清空Session级别的一级缓存;

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

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? [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的批量更新语法)

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:(强烈不推荐)

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:

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:

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 cobJzzorg.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的批量更新语法)

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:(强烈不推荐)

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:

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:

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程序设计有所帮助。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:接口管理工具平台(接口管理平台作用)
下一篇:api 网关反向代理(反向代理http)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~