我有一個懶洋洋地加載網站收集用戶模式:JUnit的休眠:測試延遲關聯獲取
@Entity
public class User {
@Id
@GeneratedValue
private Integer id;
@OneToMany(fetch = FetchType.LAZY)
private Set<Site> sites;
...
,並在我的userDAO的一個HQL查詢,加載由ID的用戶,同時也獲取了相關網站:
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Query;
import org.springframework.stereotype.Repository;
@Repository
public class userDaoImpl implements UserDao() {
@Inject
private SessionFactory sessionFactory;
public Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
public User findByIdFetchSites(final Integer id) {
String queryString = "SELECT user FROM User user LEFT JOIN FETCH user.sites WHERE user.id = :id";
Query qry = getCurrentSession().createQuery(queryString).setInteger("id", id);
return qry.uniqueResult();
}
...
我想測試一下,當我運行這個Dao方法時,站點與用戶一起被抓取。我對HSQLDB JUnit測試類運行,如下所示:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:/test-context.xml" })
@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
@Transactional
public class UserDaoImplTest {
@Inject private UserDaoImpl userDaoImpl;
@Test
public void retrievesUserFetchesSites() {
Set<Site> sites = new HashSet<Site>();
...
User user = new User();
user.setSites(sites);
userDaoImpl.saveOrUpdate(user);
User retrievedUser = userDaoImpl.findByIdFetchSites(1);
assertTrue(retrievedUser.getSites().containsAll(sites));
}
哪裏@Transactional是春事務註釋(org.springframework.transaction.annotation.Transactional)。測試通過,甚至當我運行它反對簡單findUserById DAO方法,爲此,網站都沒有明確牽強:
public User findById(final Integer id) {
String queryString = "SELECT user FROM User user WHERE user.id = :id";
Query qry = getCurrentSession().createQuery(queryString).setInteger("id", id);
return qry.uniqueResult();
}
我不完全知道爲什麼網站正在獲取斷言之前(我可以」沒有在日誌中的select語句中看到它),但是我認爲我想要做的是在斷言發生之前關閉當前會話;是這樣的:
@Test
public void retrievesUserFetchesSites() {
Set<Site> sites = new HashSet<Site>();
...
User user = new User();
user.setSites(sites);
userDaoImpl.saveOrUpdate(user);
User retrievedUser = userDaoImpl.findByIdFetchSites(1);
userDaoImpl.getCurrentSession().close();
assertTrue(retrievedUser.getSites().containsAll(sites));
}
然而,當我嘗試這樣做,我得到了以下異常:
org.springframework.transaction.TransactionSystemException: Could not roll back Hibernate transaction; nested exception is org.hibernate.TransactionException: rollback failed
at org.springframework.orm.hibernate4.HibernateTransactionManager.doRollback
我以爲是由於@DirtiesContext(我需要在每次測試之前清潔分貝)。我如何確保hibernate在測試期間不會爲我的關聯執行延遲加載?
似乎我在課堂上需要'@Transactional',或者它抱怨沒有課程...所以我應該在課堂上有'@Transactional(propagation = Propagation.REQUIRES_NEW)',然後3個方法?即:'@Test public void myTest(){insertUserWithSites(); assertSitesRetrievedWithUser(); }','@Transactional public void insertUserWithSites(){...}'和'public void assertSitesRetrievedWithUser(){...}'? – JimJay
不是。所有方法仍將共享相同的事務。如果你想保持你的方法事務性,那麼使用我的答案中解釋的第二種方法。 –