没有persist()指令的JPA持久实体
Posted
技术标签:
【中文标题】没有persist()指令的JPA持久实体【英文标题】:JPA persistent entity without persist() instruction 【发布时间】:2013-09-02 10:32:04 【问题描述】:我有这个 JPAServiceImpl 方法:
@Override
@Transactional
public void createPageContent(SellerContent content, long userId)
Seller s = em.find(Seller.class,userId);
content.setSeller(s);
content.setSeller(s);
s.addContent(content);
它可以工作,但我想知道它是如何工作的,因为没有任何
em.merge(seller)
或 em.persist(content)
。
Seller 拥有 CascadeType.ALL 与 SellerContent 关系。
如果这是正常行为,您能解释一下吗?我会写em.merge(seller)
和em.persist(content)
。错了吗?
比如我写了这个方法:
@Override
@Transactional
public void createFeedback(CartLine cartLine, String feedbackString)
Product product = cartLine.getProduct();
Feedback feedback = new Feedback();
feedback.setFeedbackContent(feedbackString);
feedback.setCartLine(cartLine);
cartLine.setFeedback(feedback);
product.getFeedbacks().add(feedback);
feedback.setProduct(product);
em.persist(feedback);
em.merge(cartLine);
em.merge(product);
在这种方法中,我编写了合并和持久化指令。错了吗?
【问题讨论】:
【参考方案1】:之所以有效,是因为您的 Seller
对象是通过实体管理器在同一事务中加载的。在运行时它将被代理对象替换。此对象的每次更改都将在事务结束时自动持久化。你可以很容易地检查它:在运行时在你的 createPageContent
方法中创建一个刹车点,然后检查 Seller s
变量的实际类型。它将是以下事情所必需的代理:
Seller s
状态的每一个变化(例如s.addContent(content)
)。在事务结束时保留这些更改。
加载惰性关系。想象一下你的Seller
有Owner
的列表。默认情况下,在运行时此列表将为空。它将在您执行s.getOwners().iterator()
时准确加载。
所以通常您只需要为使用new
关键字创建的实例调用em.persist()
。大多数时候,即使这样也没有必要:您可以将新对象A
附加到持久对象B
,然后调用em.persist(B)
。 A
将被级联持久化。
第二块代码:
我认为您可以安全地删除em.merge
呼叫。仅当您执行 CartLine mergedCartline = em.merge(cartLine); mergedCartline.doSomething()
时才需要合并。
您可以删除em.persist(feedback)
调用,如果: a) CartLine cartLine
总是通过实体管理器加载; b) cartLine.feedback
属性可以通过级联方式持久化(取决于您的映射)。
【讨论】:
@MaksymDemidas 谢谢你的解释 :) 但我有一个疑问:你说我可以为使用 new 关键字创建的实例调用em.persist()
。我使用Feedback feedback = new Feedback();
,然后使用cartLine.setFeedback(feedback);
。如果我理解,我可以删除 em.persist(feedback)
如果我得到 CascadeType=PERSIST 以上 CartLine 与反馈的关系;我说的对吗?
完美。谢谢你:)【参考方案2】:
由于您的实体处于托管状态,您不必调用percist()
方法。
【讨论】:
以上是关于没有persist()指令的JPA持久实体的主要内容,如果未能解决你的问题,请参考以下文章
创建没有 persistence.xml 配置文件的 JPA EntityManager