Shound我避免使用mappedBy来保持我的应用程序稳定? [英] Shound I avoid using mappedBy to keep my application stable?

查看:97
本文介绍了Shound我避免使用mappedBy来保持我的应用程序稳定?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  @Entity 
public class Trip {

@OneToMany(mappedBy =trip,fetch = FetchType.LAZY)
private Set< Job> jobs = new HashSet< Job>();


$ b $ @实体
公共类工作{

@ManyToOne(fetch = FetchType.LAZY)
私人旅程跳闸;






问题在于mappedBy关系在不同情况下表现不同。这里是一个例子

  EntityManager em1 = unit.createEntityManager(); 
EntityManager em2 = unit.createEntityManager();

//一个EM开始交易并存储一笔旅行
em1.getTransaction()。begin();

旅程=新旅程();
em1.persist(trip);

Long tripId = trip.getId();

assertThat(tripId).isPositive();

em1.getTransaction()。commit();

//然后em2启动不同的事务
em2.getTransaction()。begin();

//通过clean em查找旅程(缓存为空)
Trip em2Trip = em2.find(Trip.class,tripId);

Job job = new Job();
job.setTrip(em2Trip);

em2.persist(job);

// em2Trip不应该更新

assertThat(em2Trip.getJobs())。hasSize(1);

em2.getTransaction()。commit();

em1.getTransaction()。begin();

旅行em1Trip = em1.find(Trip.class,tripId);

//在这里失败
assertThat(em1Trip.getJobs())。hasSize(1);

em1.getTransaction()。commit();

上面的代码显示如果实体已经加载到实体管理器的缓存中, mappedBy关系可能会返回无效结果。



我有一个证明,它在JBoss下也不起作用。以下代码的行为有所不同,具体取决于正在使用哪个实体管理器。结果是不可预测的。

  Trip trip = em.find(Trip.class,tripId); 
if(trip.getJobs()。size()== 0)...

这是否意味着mappedBy在引入和使用后会自动生成应用程序错误?



PS我不想滥用冬眠。我只想知道是否有人遇到这样的问题,他们是如何应对的? 解决方案

与协会完全没有任何关系;如果您试图从两个实体经理读取/更新简单的POJO,您会得到完全相同的结果。一旦你的实体与持久性上下文相关联,它就不会自动从数据库中刷新。这是一种记录行为 - 在绝大多数情况下,这是一种DESIRED行为。



就保持应用程序稳定而言:


  1. EntityManager实例直接对应于休眠会话,因此不应长期保存。如果您重写上述代码以使用新的EntityManager实例(em3)而不是重复使用em1,则问题将消失。

  2. EntityManager具有 refresh()方法,您可以调用它来从数据库重新加载实体状态。

  3. EntityManager有一个 clear()方法这将完全清除持久化上下文,从而也防止了这个问题。虽然 - 调用 clear()而没有 flush()会抛弃所有挂起的更新,但谨慎谨慎地使用它。 / li>


I have two entities like the following:

@Entity
public class Trip {

    @OneToMany(mappedBy = "trip", fetch = FetchType.LAZY)
    private Set<Job> jobs = new HashSet<Job>();

}

@Entity
public class Job {

    @ManyToOne(fetch = FetchType.LAZY)
    private Trip trip;

}

The problem is that the mappedBy relationship behaves differently in different circumstances. Here is an example

    EntityManager em1 = unit.createEntityManager();
    EntityManager em2 = unit.createEntityManager();

    // One EM starts transaction and stores a trip
    em1.getTransaction().begin();

    Trip trip = new Trip();
    em1.persist(trip);

    Long tripId = trip.getId();

    assertThat(tripId).isPositive();

    em1.getTransaction().commit();

    // Then em2 starts different transaction
    em2.getTransaction().begin();

    // Looking up for the trip through clean em (cache is empty)
    Trip em2Trip = em2.find(Trip.class, tripId);

    Job job = new Job();
    job.setTrip(em2Trip);

    em2.persist(job);

    // The em2Trip should not be updated

    assertThat(em2Trip.getJobs()).hasSize(1);

    em2.getTransaction().commit();

    em1.getTransaction().begin();

    Trip em1Trip = em1.find(Trip.class, tripId);

    // fails here
    assertThat(em1Trip.getJobs()).hasSize(1);

    em1.getTransaction().commit();

The code above shows that if an entity is already loaded in the entity manager's cache, the getter for the mappedBy relationship may return invalid results.

I have a proof it doesn't work under JBoss either. The following code behaves differently depending on which entity manager is being used. The result is unpredictable.

        Trip trip = em.find(Trip.class, tripId);
        if (trip.getJobs().size() == 0) ...

Does this mean that the mappedBy automatically makes application buggy as soon as it is introduced and used?

P.S. I am not trying to abuse hibernate. I only want to find out if someone faced such a problem and how did they cope with it

解决方案

Behavior you're describing has absolutely nothing to do with associations; you would get the exact same results if you just tried to read / update simple POJO from two entity managers. Once your entity is associated with persistence context it will NOT be automatically refreshed from the database. This is a documented behavior - and in the vast majority of cases this is a DESIRED behavior.

As far as "keeping your application stable" goes:

  1. EntityManager instances directly correspond to Hibernate sessions and thus should not be held for prolonged periods of time. If you rewrite your code above to use a new EntityManager instance (em3) instead of reusing em1, your problem will go away.
  2. EntityManager has a refresh() method which you can invoke to reload entity state from the database.
  3. EntityManager has a clear() method which will clear the persistence context completely thus preventing this issue as well. Use it sparingly and cautiously, though - invoking clear() without flush() will throw away all pending updates.

这篇关于Shound我避免使用mappedBy来保持我的应用程序稳定?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆