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

我对大量域实体使用hibernate批量保存处理。 首先,当我在DB中只有一个insert实体时,我的性能没有问题。但之后,我向另一个实体添加了一对一的关系,之后我遇到了性能和内存泄漏问题。Hibernate现在一次插入两个

这里是我的域模型:

@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;
    }