OneToMany bi-directional relationship - OneToMany set is always empty
I have a OneToMany, bi-directional relationship set up with Roo/JPA. I am using the following:
Spring Roo 1.1.5.RELEASE
EclipseLink
MySQL 5.5.14
Java 1.6.0_23
Windows 7
My relationship is defined as follows:
Code:
@RooJavaBean
@RooToString
public class Baby {
@NotNull
@ManyToOne
private Mother mother;
}
The bi-directional relationship is defined by:
Code:
@RooJavaBean
@RooToString
public class Mother{
@OneToMany(cascade = {CascadeType.REMOVE }, mappedBy = "mother", fetch = FetchType.EAGER)
@OrderBy("sequence")
Set<Baby> babies= new TreeSet<Baby>();
}
Any time I use a Roo finder method to fetch a Mother from the database, the set of baby objects is always null. However, fetching a Baby from the database always has the Mother member variable set correctly. I have tried FetchType.EAGER and FetchType.LAZY. For example, the following log statement always outputs zero:
Code:
Mother m = Mother.findMother(id);
logger.info("mother has {} children", m.getBabies().size());
Thanks, any help is appreciated.
1 Attachment(s)
OneToMany set IS empty after all
After running the following Roo script:
project --topLevelPackage com.sandbox.roo --projectName roo-sandbox --java 6
persistence setup --database H2_IN_MEMORY --provider HIBERNATE
web mvc setup
entity --class ~.domain.Department --testAutomatically
entity --class com.sandbox.roo.domain.Employee --testAutomatically
field reference --fieldName department --type com.sandbox.roo.domain.Department --cardinality MANY_TO_ONE --fetch EAGER
focus --class ~.domain.Department
field set --fieldName employees --type com.sandbox.roo.domain.Employee --cardinality ONE_TO_MANY
field string --fieldName name --notNull
focus --class com.sandbox.roo.domain.Employee
field string --fieldName name --notNull
web mvc all --package ~.web
perform eclipse
You get a basic project consisting of Departments and Employees.
There is a One-To-Many relationship between Department and Employee and the fetch type is eager.
When I list the Departments, the Employees do not show up in the listing.
If I set a breakpoint in the controller, I can see that the Employee Set is not populated in the Department object after a call to entityManager.find(). The fetch type is EAGER, so why aren't the employees populated when the Department object is returned?
See attached image for an example of what is displayed.
Both sides of the relation count
Hope this is not my misunderstanding of the Active Record pattern, but traditionally one would have to satisfy both sides of the JPA relation.
JPorche, in their test, was only setting one side.
Here is a complete example in which the tests pass:
project --topLevelPackage mvm.mums --projectName mums --java 6
persistence setup --database HYPERSONIC_PERSISTENT --provider HIBERNATE
entity --class ~.model.Baby --testAutomatically
entity --class ~.model.Mother --testAutomatically
field set --fieldName babies --type ~.model.Baby --cardinality ONE_TO_MANY --mappedBy mother
focus --class ~.model.Baby
field reference --fieldName mother --type ~.model.Mother --cardinality MANY_TO_ONE
Code:
@Transactional
@Test
public void tryMe() {
Mother mum = new Mother();
Baby babs = new Baby();
// We must satisfy both sides of bi-directional relation
babs.setMother(mum);
mum.getBabies().add(babs);
mum.persist();
Mother newMumBefore = Mother.findMother(mum.getId());
Assert.isTrue(newMumBefore.getBabies().size() == 1);
mum.flush();
mum.clear();
Mother newMumAfter = Mother.findMother(mum.getId());
Assert.isTrue(newMumAfter.getBabies().size() == 1);
}
You could add convenience methods to your entities that take care of this for you, for example the Mother entity:
Code:
@RooJavaBean
@RooToString
@RooEntity
public class Mother {
@OneToMany(cascade = CascadeType.ALL, mappedBy = "mother")
private Set<Baby> babies = new HashSet<Baby>();
public void addBaby(Baby babs) {
babs.setMother(this);
getBabies().add(babs);
}
}
Hope this helped, found myself scratching my scalp over same problems.
M.
Related Question: Field set @NotEmpty
(yet another newbie using roo)
I want to add just a validations rule (@NotEmpty or @NotNull or whatever says that this collections cannot be empty) to a field set of the entity Tagging, but nothing works...
Code:
@RooJavaBean
@RooToString
@RooJpaActiveRecord(table = "taggings")
@RooJson
@RooSolrSearchable
public class Tagging extends Event {
@NotNull
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "tagging")
private Set<Tag> tags = new HashSet<Tag>();
Also to mention that Tagging extends Event as you can see...
Any help/comment more than welcome!!
Thanks,
GK