gpt4 book ai didi

java - 如何在 Hibernate 中获取

转载 作者:行者123 更新时间:2023-11-29 01:41:08 26 4
gpt4 key购买 nike

更新:我创建了一个 example on GitHub 来演示我的问题;由于 HashMap 键是一个代理对象,HibernateMapTest 目前失败了。我希望有人可以建议我可以查询实体并获取 map 以便测试通过的方法...

我只是想获取在 Hibernate 中持久保存的 HashMap 的内容,但我在找到正确的方法时遇到了一些麻烦......

HBM 映射如下,我没有创建它,但根据我的研究,它似乎是一个具有多对多关系的 ternary association mapping(更新:为了简化我的问题,我将 map 强制设置为 lazy="false"以避免我加入):

<hibernate-mapping>
<class name="database.Document" table="document">
...
<map name="documentbundles" table="document_bundles" lazy="false">
<key column="id"/>
<index-many-to-many column="pkgitemid" class="database.PkgItem"/>
<many-to-many column="child" class="database.Document" />
</map>
</class>
</hibernate-mapping>

为简单起见,我目前只是尝试获取填充了此 map 数据的所有记录:

DetachedCriteria criteria = DetachedCriteria.forClass(Document.class);
criteria.add(Restrictions.eq("id", 1));
List<Document> result = hibernateTemplate.findByCriteria(criteria);

在 last 为 false 之后,我现在无需抛出 LazyInitializationException 即可获取 Map 的内容;但是没有一个关键对象被正确初始化。我转储了一个屏幕截图来阐明我的意思:

Hashmap key is empty

我知道这些字段已填充到数据库中,我怀疑我的提取策略仍然是罪魁祸首。如何在 Hibernate 中正确获取 <map>

最佳答案

错误是由于 HibernateTemplate 打开一个 Hibernate session 来执行这个查询:

List results = hibernateTemplate.find("from database.Document d where d.name = 'doc1'");

然后在查询运行后立即关闭 session 。然后,当循环遍历键时, map 链接到的 session 关闭,因此无法再加载数据,导致代理抛出 LazyInitializationException

此异常意味着代理无法再透明地加载数据,因为链接到的 session 现在已关闭。

HibernateTemplate 的主要目标之一是了解何时打开和关闭 session 。如果有正在进行的交易,模板将保持 session 打开。

所以这里的关键是将单元测试包装在 TransactionTemplate(相当于 @Transactional 的模板)中,这会导致 session 保持打开状态 hibernate 模板。因为 session 保持打开状态,所以不会再发生惰性初始化异常。

这样修改测试即可解决问题(注意TransactionTemplate的使用):

import database.Document;
import database.PkgItem;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Set;

public class HibernateMapTest {

private static final String TEST_DIALECT = "org.hibernate.dialect.HSQLDialect";
private static final String TEST_DRIVER = "org.hsqldb.jdbcDriver";
private static final String TEST_URL = "jdbc:hsqldb:mem:adportal";
private static final String TEST_USER = "sa";
private static final String TEST_PASSWORD = "";

private HibernateTemplate hibernateTemplate;
private TransactionTemplate transactionTemplate;

@Before
public void setUp() throws Exception {
hibernateTemplate = new HibernateTemplate();
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.getHibernateProperties().put("hibernate.dialect", TEST_DIALECT);
sessionFactory.getHibernateProperties().put("hibernate.connection.driver_class", TEST_DRIVER);
sessionFactory.getHibernateProperties().put("hibernate.connection.password", TEST_PASSWORD);
sessionFactory.getHibernateProperties().put("hibernate.connection.url", TEST_URL);
sessionFactory.getHibernateProperties().put("hibernate.connection.username", TEST_USER);
sessionFactory.getHibernateProperties().put("hibernate.hbm2ddl.auto", "create");
sessionFactory.getHibernateProperties().put("hibernate.show_sql", "true");
sessionFactory.getHibernateProperties().put("hibernate.jdbc.batch_size", "0");
sessionFactory.getHibernateProperties().put("hibernate.cache.use_second_level_cache", "false");

sessionFactory.setMappingDirectoryLocations(new Resource[]{new ClassPathResource("database")});
sessionFactory.afterPropertiesSet();

hibernateTemplate.setSessionFactory(sessionFactory.getObject());

transactionTemplate = new TransactionTemplate(new HibernateTransactionManager(sessionFactory.getObject()));
}

@After
public void tearDown() throws Exception {
hibernateTemplate.getSessionFactory().close();
}

@Test
public void testFetchEntityWithMap() throws Exception {

transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
// Store the entities and mapping
PkgItem key = new PkgItem();
key.setName("pkgitem1");
hibernateTemplate.persist(key);

Document doc2 = new Document();
doc2.setName("doc2");
hibernateTemplate.persist(doc2);

Document doc1 = new Document();
doc1.setName("doc1");
HashMap<PkgItem, Document> documentbundles = new HashMap<PkgItem, Document>();
documentbundles.put(key, doc2);
doc1.setDocumentbundles(documentbundles);
hibernateTemplate.persist(doc1);

// Now attempt a query
List results = hibernateTemplate.find("from database.Document d where d.name = 'doc1'");
Document result = (Document)results.get(0);

// Check the doc was returned
Assert.assertEquals("doc1", result.getName());

key = (PkgItem)hibernateTemplate.find("from database.PkgItem").get(0);
Set<PkgItem> bundleKeys = result.getDocumentbundles().keySet();

// Check the key is still present in the map. At this point the test fails because
// the map contains a proxy object of the key...
Assert.assertEquals(key, bundleKeys.iterator().next());
}
});

}
}

更改后的测试结果和日志如下:

enter image description here

关于java - 如何在 Hibernate 中获取 <map>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21703851/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com