session.clear()分离引用实体并创建新记录

时间:2015-06-23 11:44:12

标签: hibernate session

Item.java

@Entity
@Table(name = "items")
public class Item extends Model {
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(referencedColumnName = "id", name = "parent_id")
    private Item parent;    
}

我们正在处理批处理并将其保存到数据库。在该批次中,我们Item已将父项附加到其中,如下所示

Item[id=null] {child1}
    -> ParentItem[id=null] {parent1}

现在session.save(item);调用了哪个生成了以下ID。

Item[id=129123] {child1}
    -> ParentItem[id=129122] {parent1}

现在调用session.flush();session.clear();

在该批次中,我们还有另一个Item,它附有相同的父级。

Item[id=null] {child2}
    -> ParentItem[id=null] {parent1 same object attached in child1}

技术上child2应该引用在ParentItem[id=129122]中创建的父{child1}。但是当我在session.save(item);上调用child2时,它会创建新的ParentItem。

Item[id=129125] {child2}
    -> ParentItem[id=129124] {parent1} // I want ParentItem[id=129122] should be here.
  

注意:这是因为我们调用了session.clear();

我们使用以下代码保存记录。

IntStream.range(0, items.size())
         .filter(i -> items.get(i) != null).forEach(i -> {
            T item = items.get(i);
            Item it = (Item) item;

            session.save(item);

            if (i % 50 == 0) {
                session.flush();
                session.clear();
            }
         });
tr.commit();

问题:

  • 我们应该在保存所有对象后调用session.clear();吗?

  • 如果session.clear();调用引用实体,则Hibernate无法识别附加到其他对象的对象。 [是Hibernate的规则还是我们缺少一些Hibernate配置]

可能的解决方案:

  • 在阅读了几篇文章之后,他们建议使用StatelessSession

你的建议是什么?

修改

我使用StatelessSession#insert然后抛出异常。这意味着我们要明确保存附加的父项(我们不希望这样),还有其他方法吗?

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.org.openxcell.model.Item
    at org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:294)
    at org.hibernate.type.EntityType.getIdentifier(EntityType.java:537)
    at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:165)
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2843)
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2818)
    at org.hibernate.persister.entity.AbstractEntityPersister$4.bindValues(AbstractEntityPersister.java:3025)
    at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3032)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3558)
    at org.hibernate.internal.StatelessSessionImpl.insert(StatelessSessionImpl.java:141)
    at org.hibernate.internal.StatelessSessionImpl.insert(StatelessSessionImpl.java:123)

1 个答案:

答案 0 :(得分:0)

您正在使用OneToOne映射。如果您想要有许多具有相同父项的项目,则必须使用ManyToOne映射。