Hibernate批量保存性能
我对大量域实体使用hibernate批量保存处理。 首先,当我在DB中只有一个insert实体时,我的性能没有问题。但之后,我向另一个实体添加了一对一的关系,之后我遇到了性能和内存泄漏问题。Hibernate现在一次插入两个 这里是我的域模型:Hibernate批量保存性能,hibernate,memory-leaks,full-text-search,Hibernate,Memory Leaks,Full Text Search,我对大量域实体使用hibernate批量保存处理。 首先,当我在DB中只有一个insert实体时,我的性能没有问题。但之后,我向另一个实体添加了一对一的关系,之后我遇到了性能和内存泄漏问题。Hibernate现在一次插入两个 这里是我的域模型: @Entity @Table(name = "PRODUCT", uniqueConstraints = { @UniqueConstraint(columnNames = { "UPC" }) }) @Cache(usage = CacheConcur
@Entity
@Table(name = "PRODUCT", uniqueConstraints = { @UniqueConstraint(columnNames = { "UPC" }) })
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Product {
@Id
@Column(name = "PRODUCT_ID", columnDefinition = "bigint")
@Index(name = "PRODUCT_ID_IDX")
private Long id;
@Column(name = "UPC")
private String upc;
@Column(name = "CURRENCY")
private String currency;
@Column(name = "RETAIL_PRICE")
private Double retailPrice;
@Column(name = "SALE_PRICE")
@Index(name = "PRODUCT_PRICE_IDX")
private Double salePrice;
@Type(type = "true_false")
@Column(name = "INSTOCK")
private boolean instock;
@Column(name = "SHIPPING")
private Double shipping;
@Column(name = "RATING")
private Integer rating;
@Column(name = "VIEWS")
@Index(name = "PRODUCT_VIEWS_IDX")
private Long views;
@OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
@JoinColumn(name = "PRODUCT_ID", nullable = false)
@Index(name = "PRODUCT_ID_REVIEW_IDX")
private List<ProductReview> reviews = new ArrayList<ProductReview>();
//Here is new relation
@OneToOne(fetch = FetchType.LAZY, mappedBy = "product", cascade = CascadeType.ALL)
private ProductInformation information;
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnore
@JoinColumn(name = "CATEGORY_ID", nullable = true)
@Index(name = "PRODUCT_CAT_IDX")
private ProductCategory category;
@ManyToOne(fetch = FetchType.LAZY)
@JsonIgnore
@JoinColumn(name = "BRAND_ID", nullable = true)
@Index(name = "PRODUCT_BRAND_IDX")
private ProductBrand brand;
如何设置我的产品:
result.setInformation(info);
info.setProduct(result);
我的DAO方法:
@Override
@Transactional(propagation = Propagation.REQUIRED)
public int batchSave(List<Product> products, int batchSize) {
int insertedCount = 0;
Session batchSession = null;
Transaction batchTransaction = null;
try {
batchSession = getSessionFactory().openSession();
batchTransaction = batchStateLessSession.beginTransaction();
for (Product product : products) {
//First I used save() but this method calls select before insert and this //not a good idea.
//batchSession.save(product);
batchSession.persist(product);
if (++insertedCount % batchSize == 0) {
batchSession.flush();
batchSession.clear();
}
}
batchSession.flush();
batchSession.clear();
batchTransaction.commit();
batchSession.close();
} catch (ConstraintViolationException ex) {
if (batchSession != null && batchTransaction != null) {
batchSession.clear();
batchTransaction.commit();
batchSession.close();
}
}
return insertedCount;
}
@覆盖
@事务性(传播=传播。必需)
public int batchSave(列出产品,int batchSize){
int insertedCount=0;
会话batchSession=null;
事务批处理事务=null;
试一试{
batchSession=getSessionFactory().openSession();
batchTransaction=BatchStatesession.beginTransaction();
用于(产品:产品){
//首先,我使用了save(),但是这个方法在插入之前调用select,这个//不是一个好主意。
//batchSession.save(产品);
batchSession.persist(产品);
如果(++insertedCount%batchSize==0){
batchSession.flush();
batchSession.clear();
}
}
batchSession.flush();
batchSession.clear();
batchTransaction.commit();
batchSession.close();
}捕获(ConstraintViolationException ex){
if(batchSession!=null&&batchTransaction!=null){
batchSession.clear();
batchTransaction.commit();
batchSession.close();
}
}
返回insertedCount;
}
我的批量大小是50行。所有hibernate属性都已正确设置。
我不使用无状态会话,因为我需要在实体上创建全文搜索索引。
我在保存了30K个实体后发生内存泄漏。但是我的XML文件有1000万个条目。
当我没有ProductInformation实体并且所有字段都存储在Product实体中时,所有字段都可以完美地工作,没有任何泄漏
你知道我的问题吗?
也许我应该使用无状态会话,并在插入所有行后在10M行表上创建全文索引?您使用的是什么数据库?除了SQL之外还有脚本语言吗?用您正在使用的数据库替换“batch”标记,这可能是让正确的人看到这一点的开始。你的问题也可以使用更好的措辞和格式。
@Override
@Transactional(propagation = Propagation.REQUIRED)
public int batchSave(List<Product> products, int batchSize) {
int insertedCount = 0;
Session batchSession = null;
Transaction batchTransaction = null;
try {
batchSession = getSessionFactory().openSession();
batchTransaction = batchStateLessSession.beginTransaction();
for (Product product : products) {
//First I used save() but this method calls select before insert and this //not a good idea.
//batchSession.save(product);
batchSession.persist(product);
if (++insertedCount % batchSize == 0) {
batchSession.flush();
batchSession.clear();
}
}
batchSession.flush();
batchSession.clear();
batchTransaction.commit();
batchSession.close();
} catch (ConstraintViolationException ex) {
if (batchSession != null && batchTransaction != null) {
batchSession.clear();
batchTransaction.commit();
batchSession.close();
}
}
return insertedCount;
}