我有一個類似博客的情況下,有兩個Java類:郵政和標籤,這是一個@ManyToMany關係,具有Post_Tag關聯表,這裏是我的簡單的定義:@ManyToMany不一致的數據
public class Post
{
@ManyToMany(fetch=FetchType.LAZY)
@Fetch(FetchMode.SELECT)
@JoinTable(name = "Post_Tag"
, joinColumns = @JoinColumn(name="Post_id")
, inverseJoinColumns = @JoinColumn(name="Tag_id")
)
private Set<PostTag> tags = new HashSet<PostTag>();
}
public class Tag
{
@ManyToMany(mappedBy="tags" , fetch=FetchType.LAZY)
private Set<Post> comments = new HashSet<Post>();
}
似乎確定,但在下面的測試場景失敗:
- 創建一個標籤,標籤1
- 創造第一位後,POST1
- 創建第二個帖子,POST2
- 外接TAG1到post1.getTags()和post2.getTags()
- 更新POST1,POST2
- 列表列表= dao.getPostByTag(TAG1)
- 斷言則爲list.size()== 2 ,失敗
這裏是我的測試代碼:
public void testGetCommentsByTag()
{
Tag tag1 = tagDao.save(new Tag("tag1"));
assertTrue(tag1.getId() > 0);
Post post1 = dao.save("...");
Post post2 = dao.save("...");
post1.getTags().add(tag1);
post2.getTags().add(tag1);
dao.update(post1);
dao.update(post2);
List<Post> list = dao.getPostsByTag(tag1 , 0 , 100);
assertSame(2 , list.size()); // FAILED !
assertTrue(list.contains(post1));
assertTrue(list.contains(post2));
}
這裏是我的dao.getPostsByTag()的實現:
public List<Post> getPostsByTag(Tag tag , int start, int count)
{
Session session = (Session) em.getDelegate();
Criteria c = session.createCriteria(Post.class);
c.createCriteria("tags")
.add(Restrictions.eq("id", tag.getId()));
c.setFirstResult(start);
c.setMaxResults(count);
c.setCacheable(true);
return c.list();
}
返回的列表大小== 0! 我注意到了生成的SQL命令,發現hibernate先getPostsByTag()然後插入關聯表,這會使getPostsByTag()返回0長度列表。 :
Hibernate:
insert
into
Tag
values
(?, ?, ?, ?)
Hibernate:
insert
into
Post
(...)
values
(???)
Hibernate:
insert
into
Post
(...)
values
(???)
Hibernate:
select
ooxx
from
Post this_
inner join
Post_Tag tags3_
on this_.id=tags3_.Post_id
inner join
Tag tag1_
on tags3_.Tag_id=tag1_.id
where
and tag1_.id=?
order by
this_.created desc limit ?
Hibernate:
insert
into
Post_Tag
(Post_id, Tag_id)
values
(?, ?)
Hibernate:
insert
into
Post_Tag
(Post_id, Tag_id)
values
(?, ?)
如何確保getPostsByTag()被執行after
插入關聯表?
我知道在spring-JUnit3中有'endTransaction()和startNewTransaction()'方法,但在spring-with-junit4中似乎不可用。
但我不知道如何在one
事務中通過此測試? 謝謝。
環境:Spring4(基於SpringJUnit4ClassRunner),休眠-3.5.6,JPA 2.0
您好,我嘗試了第二種方式,仔細管理關聯的兩端,但dao.getPostsByTag()仍然在hibernate插入關聯表之前執行。我嘗試在dao.getPostsByTag()之前插入tagDao.update(tag1),但仍然是相同的錯誤答案(空列表)。 – smallufo 2010-11-16 04:45:27
你嘗試過調用session.flush()嗎? – RMorrisey 2010-11-16 05:17:50
嗨,我有問題調用session.flush(),因爲它是一個測試類,這是超出休眠範圍。這些DAO(postDao,tagDao)被注入到類中(在spring中)。測試類不知道底層的實現。是的,可能有某種方法可以從threadLocal或其他東西中獲取當前綁定的會話,但我認爲這不是在測試類中「刷新會話」的正常方法。應該有一些方法讓hibernate'知道'它應該在更新關聯表後執行getPostsByTag(),不是嗎? – smallufo 2010-11-16 05:49:07