我有一个类似博客的情况下,有两个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