Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] OneToMany list insertion problem

I can't really tell how your transactions begin and end in the pseudo code you have provided. Before going into that, I'd like to suggest you try a more recent version of EclipseLink. We have fixed a couple of bugs related to lists since 2.1.3. One that jumps out at me is this one:

https://bugs.eclipse.org/bugs/show_bug.cgi?id=346022

Although, the bug describes an issue with ManyToMany, the fix would cover other collections as well.

I suggest verifying you still see an issue on EclipseLink 2.3.2.

-Tom

On 28/02/2012 11:52 AM, Renee Revis wrote:

What I mean is that I make many requests to get questions. In each transaction,
I remove a question line from the list, update the ranking, add the line back
into the list and then return the question to the user.

When I'm debugging, I'm just comparing the difference between two of these
transactions. Everything seems fine at the end of the first one, just before the
commit, but when I check the data at start of the next request/transaction, I
find the situation of one question line no longer showing up in the list. It's
still there, because the JPA query finds it, but the list in the entity no
longer references it.

I'm using EclipseLink 2.1.3 - Helios with GlassFish 3.1.1. I get the entity
manager through injection:

@PersistenceContext(unitName = "UserDB_Lib")
private EntityManager userEm;

Here are some relevant lines (with some unnecessary detail removed):

When the transaction first starts, we get the group we want to use. I display
the number of lines in the list and log the list elements with the
showQuestionLines routine, as well as show the number of lines we found in the
db with the query.


nextQuestionGroup = userGame.getQuestionGroups().remove(0);
logger.info("use group: " + <ref>.getName() + ", with num lines: " +
<ref>.getQuestionLines().size());
showQuestionLines(userEm, nextQuestionGroup);
dbLines = userEm.createNamedQuery("...").<setParams>.getResultList();
logger.info("num lines found in db: " + dbLines.size());
nextQuestionLine = nextQuestionGroup.getQuestionLines().remove(0);


Then we use the question line, update the ranking, and add it back in as shown
below. I display the number of elements and the element list again, which, as
I've said, looks correct at this point for the first transaction, but at the
start of the next transaction, it's different. I'm pretty sure the flush command
is unnecessary because this is the end of the transaction, but I've been trying
anything I could think of.

I'm using the reference to the same element that I removed from the list (i.e.,
nextQuestionLine). That is still a persisted entity, right? I'm not somehow
getting a copy of it and so adding back in an unpersisted entity to the list, am I?


// Add the question line back into the group, likely with an updated ranking and
thus, position in the list
nextQuestionGroup.addUserSelectorQuestionLine(nextQuestionLine);


// Add the question group back into the game. It will be re-ordered by the new
min ranking
userSelectorGame.addQuestionGroup(nextQuestionGroup);


logger.info("after, num lines for group: " +
nextQuestionGroup.getQuestionLines().size());
logger.info("after, num groups for game: " + userGame.getQuestionGroups().size());
showQuestionLines(userEm, nextQuestionGroup);
userEm.flush();



On Feb 28, 2012, at 11:08 AM, Tom Ware wrote:

You mention you are making two requests, the first to make changes to the
list, and the second where you see the problem. Can you please give some more
details about how this is work.

How are the transactions delineated? Is the first one finished by the time the
2nd one starts?

How are you getting the EntityManagers?

Can you give some pseudo code for each request?

What version of EclipseLink are you using?

-Tom

On 28/02/2012 10:39 AM, Renee Revis wrote:

I have a bi-directional ManyToOne mapping between two entities. I maintain the
order of the list on the OneToMany side based on a ranking field. Initially I
can create the entities and everything is fine. After that, when I use a
question line, I remove it from the list, update the ranking and then add it
back into the list based on the new ranking value. I realize that the ManyToOne
side is the owning side and it's up to me to maintain the list order in memory
on the ManyToOne side, so that's what I'm trying to do.

Everything seems to work fine at first. Just before the EJB transaction
finishes, I log the elements of the list and everything is as I expect. However,
when I make the next request (i.e., a new EJB transaction), the list shows that
the element was removed from the list, but never added back in. This doesn't
match what it previously showed, however, in the first EJB transaction context.

If I do a JPA query for the elements that are actually in the database, all of
the elements are there. And if I restart the server to force everything to be
restored from the database, it all comes back as I expected (i.e., with the
element in the list and ordered as I expected), so it seems to be a caching
issue somehow with the persistence context. I can't figure out why, in the new
transaction, I would see the change from removing the element, but not from
inserting it. They both happen in the same transaction so I should see either
both changes or neither.

Does anyone have any ideas as to what might be causing this problem? I've tried
a variety of things, and nothing has worked so far.

Thanks for any help,
Renee



The relevant parts of the entities are:

public class UserSelectorQuestionLine implements Serializable {
private Integer ranking;
@ManyToOne
private UserSelectorQuestionGroup questionGroup;
}

and

public class UserSelectorQuestionGroup implements Serializable {
@OrderBy("ranking ASC")
@OneToMany(fetch=FetchType.EAGER, mappedBy="questionGroup")
private List<UserSelectorQuestionLine> questionLines;
}


And the routine I use to add an element into the list in the
UserSelectorQuestionGroup class is:

public void addUserSelectorQuestionLine(UserSelectorQuestionLine
newUserSelectorQuestionLine) {
int index=0;
Random gen = new Random();

if (this.questionLines.size() == 0) {
this.questionLines.add(newUserSelectorQuestionLine);
} else {
for (UserSelectorQuestionLine nextQuestionLine : this.questionLines) {
if (newUserSelectorQuestionLine.getRanking() < nextQuestionLine.getRanking()) {
break;
} else if
(newUserSelectorQuestionLine.getRanking().equals(nextQuestionLine.getRanking()))
{
// We want to mix up the order of the question lines that have equal ranking
if (gen.nextInt(2) == 1) {
break;
}
}
index++;
}
this.questionLines.add(index, newUserSelectorQuestionLine);
}
this.minRanking = questionLines.get(0).getRanking();
}

I know this routine is called and is working correctly because I can display the
elements of the list in the log after this is called and everything is as
expected in the first EJB transaction context.



_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx <mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users
_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx <mailto:eclipselink-users@xxxxxxxxxxx>
https://dev.eclipse.org/mailman/listinfo/eclipselink-users



_______________________________________________
eclipselink-users mailing list
eclipselink-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/eclipselink-users


Back to the top