hibernate - @ManyToMany inconsistent data on both side problem -
i have blog-like scenario , 2 java classes : post , tag , @manytomany relationship , post_tag association table , here simplified definitions:
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>(); }
it seems ok , fails in following testing scenario :
- create tag , tag1
- create 1st post , post1
- create 2nd post , post2
- add tag1 post1.gettags() , post2.gettags()
- update post1 , post2
- list list = dao.getpostbytag(tag1)
- assert list.size() == 2 , failed
here test code :
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)); }
and here dao.getpostsbytag()'s implementation :
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(); }
the returned list size == 0 ! noticed generated sql command , found hibernate first getpostsbytag() , insert association table , makes getpostsbytag() return 0-length list. :
hibernate: insert tag values (?, ?, ?, ?) hibernate: insert post (...) values (???) hibernate: insert post (...) values (???) hibernate: select ooxx post this_ inner join post_tag tags3_ on this_.id=tags3_.post_id inner join tag tag1_ on tags3_.tag_id=tag1_.id , tag1_.id=? order this_.created desc limit ? hibernate: insert post_tag (post_id, tag_id) values (?, ?) hibernate: insert post_tag (post_id, tag_id) values (?, ?)
how make sure getpostsbytag() executed after
inserting association table ?
i know there 'endtransaction() , , startnewtransaction()' methods in spring-junit3 , seems not available in spring-with-junit4.
but wonder how can pass test in one
transaction ? thanks.
environments : spring4 (springjunit4classrunner) , hibernate-3.5.6 , jpa 2.0
you can create 2 methods in test class executed each time test method called. these methods open transaction , rollback after it:
@before public void setup() throws exception { em.gettransaction().begin(); } @after public void teardown() throws exception { em.gettransaction().rollback(); }
you should check if have flushmode different deffault because flushs made before query...
Comments
Post a Comment