【问题标题】:Problem with Hibernate find methodHibernate find 方法的问题
【发布时间】:2010-01-27 12:53:47
【问题描述】:

更新:澄清示例 我将举例说明正在发生的事情,以澄清我的 Spring + Hibernate 应用程序中的情况。 想象一下我有这两个实体(假设 getter 和 setter 也存在)

@Entity
public class Class1(){
  private Integer id;

  @OneToOne
  private Class2 object2;
}

@Entity
public class Class2(){
  private Integer id;

  @OneToOne
  private Class1 object2;
}

所以在我的数据库中,我有两个表来映射每个对象的每个实例。假设我在数据库中存储了这些对象:

  • objectA(类 Class1):id = 1,object2 = objectB
  • objectB(Class2 类):id = 2,object2 = objectA
  • objectC(类 Class2):id = 3,object2 = null 这意味着 A 和 B 是链接的。假设现在我想将 objectA 链接到 objectC。这意味着我也必须删除 objectB 中的链接。

为此,我执行以下操作:

//I get the objectA from database
Class1 storedObjectA = myservice.find(objectAId);
//Now in storedObject1 I have the same as what it is stored as objectA

//I change only the object2 attribute of it
storedObject1.setObject2(objectC);

//I search again in the database to see objectA
Class1 reStoredObjectA = myservice.find(objectAId);

restoredObjectA 现在是:

  • restoredObjectA (class= Class1) id = 1, object2 = objectC

虽然在数据库中有:

  • restoredObjectA (class= Class1) id = 1, object2 = objectB

find 方法没有在数据库中搜索,虽然我禁用了查询和二级缓存,但我已经获得了先前的搜索。方法 find 只进入它在 entityManager.find(Class1.class, id) 上执行的 DAO 如何在数据库中进行第二次查找搜索?

谢谢


(完整解释)

你好,

我有一个使用 Spring 3 和 Hibernate 的应用程序。我有一个名为 Class1 的实体,它存储在数据库中。此实体具有指向另一个名为 Class2 的实体的 OneToOne 链接。 Class2 有另一个指向 Class1 的 OneToOne 链接,并且两个链接的唯一属性都设置为 true。

我的控制器中有以下代码:

//I have an object called dataFromUser which is instance of Class1 and
// it is obtained via @ModelAttribute annotation from a form

Integer id = dataFromUser.getId();

//I get correctly the stored object from the database
Class1 storedData = myService.find(id); //this will call em.find of hibernate

//I set to the stored data the attribute I want to change
storedData.setObject2();

//I save again the object
myService.save(storedData);

myService 中的方法 save 将使用实体管理器来持久化数据,但在此之前它将检查 Class1 对象和 Class2 对象之间的先前关联以将其删除,以防新的 Class2 对象已设置为 Class1 的实例。出于这个原因,我必须再次调用 find 方法来查看我的数据库中的内容

在服务中:

@Transactional
public void save(Class1 object1){
   Class1 objectFromDB =  myDAO.find(object1.getId());
   // ....  update the old object and save
}

问题是 Service 中的 objectFromDB 与我在控制器中执行 myService.find(id) 时不同。问题是它不是在数据库中寻找它,而是在内存中搜索。我知道是因为调用第二个 find() 方法时没有记录 SQL 语句。正如我对 storedData 对象所做的 setObject2() 一样,当我第二次调用 find 方法时,我得到的正是这个对象,并且数据库不包含它,因为它还没有被持久化。

我试图在我的配置中禁用缓存只是为了尝试,但它仍在发生。我有一个具有这种配置的 ehCache:

在 persistence.xml 我有这个属性(我已经将两个缓存都设置为 false):

    <properties>
     <!-- Hibernate 3.5.0 - try org.hibernate.cache.* package -->
  <property name="hibernate.cache.provider_class"
               value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" />
   <property name="hibernate.cache.use_query_cache" value="false" />
  <property name="hibernate.cache.use_second_level_cache" value="false" />
  <property name="hibernate.generate_statistics" value="true" />
  <property name="hibernate.cache.use_structured_entries" value="false" />
  <property name="hibernate.format_sql" value="true" />
  <!-- http://www.jroller.com/eyallupu/entry/hibernate_s_hbm2ddl_tool -->
  <!-- create, create-drop, update, validate -->
  <property name="hibernate.hbm2ddl.auto" value="update" />
    </properties>  

在我的 ehcache.xml 中,我将 maxElementsInMemory 设置为 0 并将 overflowToDisk 设置为 false 以禁用它。

有什么办法可以避免这种情况吗?

谢谢。

【问题讨论】:

    标签: hibernate spring jpa caching


    【解决方案1】:

    我不确定我是否理解正确,但以防万一......


    两种加载对象的方法。如果对象不在当前内存上下文中,则存在差异:

    • 肯定会访问数据库,如果存在则返回实例,否则返回 null。
    • 另一个只是创建一个具有正确 id 的代理,而不是立即进入数据库,并将在以后的操作中根据需要处理它(可能在刷新时)。

    您似乎正在使用第二个,也许您可​​以尝试第一个,看看它是否解决了您的问题?

    【讨论】:

      【解决方案2】:

      好的,我知道了。问题是hibernate在搜索数据库之前会在它的Session中寻找对象。所以我必须在修改它之前将对象分离到会话中。在休眠中这样做:

          //being em my EntityManager instance
          Session session = (Session) em.getDelegate();
          session.evict(plan); 
          //Now the find object will not get the object wich is in session 
          //but the one in database
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-05
        • 1970-01-01
        • 1970-01-01
        • 2011-11-06
        • 2017-02-11
        • 2011-04-29
        相关资源
        最近更新 更多