Hibernate中Transaction事务的批量提交

来源:互联网 发布:网络教育本科学位难吗 编辑:程序博客网 时间:2024/06/05 18:47

  在研究Hibernate的时候,书上的例子总是一次开一个事务,通过Session对象的save()方法使其持续化并保存数据,通过提交Transaction对象将数据插入到数据库,突然想到:我们可不可以开一个事务,然后通过for循环批量产生数据,通过Session对象的save()方法保存数据,数据全部保存后统一提交事务。这样就避免了连续建立事务。

下面为实验代码:

1:Person.java

package com.mao;import java.util.Date;import javax.persistence.*;@Entity@Table(name="person_inf")public class Person {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)private Integer id;@Column (name="person_name",length=50)private String name;@Lob@Basic(fetch=FetchType.LAZY)private byte[]pic;//通过@Temporal注解 可以完成持久化属性映射到数据库的格式@Temporal(TemporalType.DATE)private Date birth;//省略所有set、get方法}

2:主程序 PersonManager.java

package com.mao;import java.io.File;import java.io.FileInputStream;import java.util.Date;import org.hibernate.*;import org.hibernate.cfg.Configuration;import org.hibernate.service.ServiceRegistry;import org.hibernate.service.ServiceRegistryBuilder;public class PersonManager {public static void main(String[]args) throws Exception{Configuration cof=new Configuration().configure();ServiceRegistryBuilder serviceRegistryBuilder=new ServiceRegistryBuilder().applySettings(cof.getProperties());ServiceRegistry registry=serviceRegistryBuilder.buildServiceRegistry();SessionFactory sf=cof.buildSessionFactory(registry);Session sess=sf.openSession();Transaction tx=sess.beginTransaction();for(int i=1;i<5;i++){        Person person=new Person();person.setName("VipMao"+i);File file=new File("image/2.jpg");byte[]content=new byte[(int) file.length()];//创建读取数据流来读取图片对象file并存入字节数组contentnew FileInputStream(file).read(content);person.setPic(content);person.setBirth(new Date());System.out.println("日期为:"+new Date());sess.save(person);}tx.commit();sess.close();sf.close();}}

可以看出:我们只创建了一次Session对象和事务对象,当所有数据创建完毕并保存后统一提交事务。

注意:我们这里将创建Person对象放在了for循环里面,后面讲说放在外面的结果。

3:运行结果

运行后查看数据库是没有问题的


4:容易出现的问题

1:将创建Person对象放到for循环外。

  这就相当于我们创建了一个事务,然后创建一个Person实例,然后我们再批量生成数据,这个时候我们生成一条数据,然后再生成一条数据时就会覆盖前一条数据,最后我们保存到数据库的只是最后一条数据,控制台输出:


这就说明了创建完Person实例后,第一条数据确实是插入到数据库,但是以后每产生一条数据后就会更新到数据库从而覆盖前面的数据,一直到更新最后一条数据,因此数据库保存的只是最后一条数据:


正确做法就是每产生一条数据就创建一个Person实例(将Person实例放到循环内),这样就可以每次产生新数据都会插入到数据库,而不是更新。

2:将Transaction事务提交放到循环内

  这就相当于第一次保存数据后就提交了事务,导致后面再需要保存数据时事务无法打开,查看控制台输出:


可以看出第一次数据提交后,导致事务开启失败。

提示:当我们通过session.save(person)之后我们只是将Java类的属性持久化,但是你不提交事务,它并不会映射到数据库的列并创建它们。


0 0