Home » Eclipse Projects » EclipseLink » Merge behavior
Merge behavior [message #1071091] |
Fri, 19 July 2013 10:29 |
Marco Quaranta Messages: 6 Registered: July 2013 |
Junior Member |
|
|
Hello,
I'd like to know if behaviour I'm going to explain is correct.
I've a Parent with several Collection<Child> relationship (@OneToMany, lazy fatch and no cascade).
Merging Parent makes Eclipselink executing several select statement, one for each child collections.
The code that issues these statements is in the method mergeIntoObject(Object target, boolean isTargetUnInitialized, Object source, MergeManager mergeManager, AbstractSession targetSession) class org.eclipse.persistence.mappings.CollectionMapping
in this line:
// BUG#5190470 Must force instantiation of indirection
containerPolicy.sizeFor(valueOfTarget);
Is this behavoir correct? I've experienced really low performance doing merge in this way.
My Eclipselink version is 2.3.2
Thanks,
Marco
[Updated on: Tue, 23 July 2013 07:19] Report message to a moderator
|
|
| | | | | |
Re: Merge behavior [message #1140240 is a reply to message #1071091] |
Wed, 16 October 2013 08:11 |
Marco Quaranta Messages: 6 Registered: July 2013 |
Junior Member |
|
|
Hello,
I'll try to explain using an example.
Suppose I have two entities: Student and Presentation.
Presentation has a FK to Student, on JPA layer there is a bidirectional relation between Presentation and Student.
@Entity
public class Student{
...
@OneToMany(mappedBy="student")
private List<Presentation> presentations;
private String firstName;
private int yearjoined;
...
}
@Entity
public class Presentation{
...
@ManyToOne
@JoinColumn(name = "STUDENT_ID")
private Student student;
private String topic;
...
}
I execute the following code:
Student s = new Student(); // Empty costructor does nothing (ie. does not initialize presentations)
s.setId(1);
s.setYearjoined(100);
em.merge(s);
Eclipselink will issues the following queries:
1) --SELECT ID, FIRSTNAME, LASTNAME, ROLLNUMBER, SCORE, DEPT, NUMBER, YEARJOINED FROM STUDENT WHERE (ID = ?) -- bind => [1] 2) --SELECT ID, GRADED, MARKSOBTAINED, TOPIC, STUDENT_ID FROM PRESENTATION WHERE (STUDENT_ID = ?) -- bind => [1] 3) --UPDATE STUDENT SET FIRSTNAME = ?, LASTNAME = ?, ROLLNUMBER = ?, SCORE = ?, DEPT = ?, NUMBER = ?, YEARJOINED = ? WHERE (ID = ?) bind => [null, null, null, 0, null, null, 100, 1]
Now, the question is: is there a way to avoid the query number 2?
I'd like to not query the DB if my student has thousand or even million presentations.
I have tried the same with Hiberante and this is the output:
1) select student0_.id as id13_0_, student0_.dept as dept13_0_, student0_.number as number13_0_, student0_.yearjoined as yearjoined13_0_, student0_.firstname as firstname13_0_, student0_.lastname as lastname13_0_, student0_.rollnumber as rollnumber13_0_, student0_.score as score13_0_ from Student student0_ where student0_.id=?
2) update Student set dept=?, number=?, yearjoined=?, firstname=?, lastname=?, rollnumber=?, score=? where id=?
Why does Eclipselink need this query?
Thank you
Marco
|
|
| | | |
Re: Merge behavior [message #1148401 is a reply to message #1145505] |
Mon, 21 October 2013 13:31 |
Chris Delahunt Messages: 1389 Registered: July 2009 |
Senior Member |
|
|
Up to now, you have not mentioned you are using a stub, and have been asking if it is JPA compliant. So to answer your prior questions, the merge behavior is expected and and required by the JPA specification - you have null values in your entity state that need to be merged into the managed Entity. If you check your managed entity after the merge, you will see it no longer has any presentations - the collection will now be null and your object model will no longer match what you have in the database.
I see what you are saying that the query isn't strictly needed, as this mapping does not really control the relationship, it could be ignored. Feel free to file a feature request to avoid instantiating the 1:m bidirectional collection on merge when its been nulled out, or even create your own 1:M class instance to use instead with the change. But your design will still result in your cache becoming corrupt or worse a loss of data with other mappings - the entity should be used, not an empty stub for the em.merge call. If you are unable to change the application, you could make your own merge method that uses em.find or getReference and then merges non-null attributes into the entity - allowing your app to still pass around stubs internally.
Best Regards,
Chris
[Updated on: Mon, 21 October 2013 13:32] Report message to a moderator
|
|
|
Goto Forum:
Current Time: Wed Feb 05 12:57:52 GMT 2025
Powered by FUDForum. Page generated in 0.04863 seconds
|