Hibernate Batch Save Perfomance
===

I have some problem and couple of questions.

I use hibernate batch save processing for large amount of my domain entities.
First, when I had only single entity for insert in DB I didn`t have problems with performance. But than I had added one-to-one relationship to another entity and after that I had problems with perfomance and memory leaks. Hibernate now did two insert at a time.

Here my domain model:

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

ProductInformation entity:

    @Indexed
    @Entity
    @Table(name = "PRODUCT_INFO")
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
    public class ProductInformation {
    
        @Id
        @DocumentId
        @Column(name = "PRODUCT_ID", columnDefinition = "integer", unique = true, nullable = false)
        private Long id;
    
        @Column(name = "BUY_URL")
        private String buyUrl;
    
        @Column(name = "IMAGE_URL")
        private String imageUrl;
    
        @Column(name = "NAME", length = 10000)
        @Fields({
            @Field(index = org.hibernate.search.annotations.Index.TOKENIZED, analyzer = @Analyzer(impl = LowercaseKeywordAnalyzer.class)),
            @Field(name = "name", index = org.hibernate.search.annotations.Index.TOKENIZED, analyzer = @Analyzer(impl = LowercaseKeywordAnalyzer.class)) })
        @Index(name = "product_info_name_idx")
        private String name;
    
        @Column(name = "LONG_DESCRIPTION", length = 10000)
        private String longDescription;
    
        @Column(name = "SHORT_DESCRIPTION", length = 10000)
        private String shortDescription;
        
        @Column(name = "KEYWORDS", length = 10000)
        private String keywords;
    
        @OneToOne(fetch = FetchType.LAZY)
        @PrimaryKeyJoinColumn
        private Product product;
How I setup my product:

    result.setInformation(info);
        info.setProduct(result);

My DAO method:

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

My batch size is 50 rows. All hibernate properties are setup correctly.
I don`t use StatelessSession because I need create fulltext search indexes on my entity.
I have memory leak after save 30K entites. But my XML file has 10M entries.
When I didn`t have ProductInformation entity and all fields were stored in Product entity, all worked perfectly without any leaks.

Have you any idea about my problem?
Maybe I should use StatelessSession and after insertion all rows create fulltext indexes on 10M rows table?