Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > EJB - retrieving the entity you've just persisted (with autogenerated key)

Reply
Thread Tools

EJB - retrieving the entity you've just persisted (with autogenerated key)

 
 
ses
Guest
Posts: n/a
 
      02-24-2011
I assume this must be a fairly common task but I'm struggling to find
the best way to achieve this.

How do you best retrieve the entity you've just persisted with
entityManager.persist(myEntity), so that you can then use it in the
next part of a transaction.

I'm referring to an entity for which the container or database manages
a generated primary key. Therefore you want to retrieve what you've
just persisted so that you can for example establish another
relationship - e.g. anotherEntity.add(myEntity) then
entityManager.merge(anotherEntity).

I am trying to do this in a session bean method and carry it out all
as one transaction. The way I am retrieving myEntity after persisting
is simply selecting the entity with the highest key value (is simple
auto increment in MySQL) but there is some problem with this. It
retrieves the entity fine with its newly generated key, however when I
try to merge it or merge another entity with which I establish a
relationship to myEntity I get the following exception:

"null primary key encountered in unit of work"

Any help would be much appreciated, I'm really asking if there is a
better way to do this (persist-find-merge in a transactional EJB
session bean method doesn't seem to be a good pattern, or at least
doesn't seem to be working for me!)
 
Reply With Quote
 
 
 
 
Daniele Futtorovic
Guest
Posts: n/a
 
      02-24-2011
On 24/02/2011 15:11, ses allegedly wrote:
> I assume this must be a fairly common task but I'm struggling to find
> the best way to achieve this.
>
> How do you best retrieve the entity you've just persisted with
> entityManager.persist(myEntity), so that you can then use it in the
> next part of a transaction.
>
> I'm referring to an entity for which the container or database manages
> a generated primary key. Therefore you want to retrieve what you've
> just persisted so that you can for example establish another
> relationship - e.g. anotherEntity.add(myEntity) then
> entityManager.merge(anotherEntity).
>
> I am trying to do this in a session bean method and carry it out all
> as one transaction. The way I am retrieving myEntity after persisting
> is simply selecting the entity with the highest key value (is simple
> auto increment in MySQL) but there is some problem with this. It
> retrieves the entity fine with its newly generated key, however when I
> try to merge it or merge another entity with which I establish a
> relationship to myEntity I get the following exception:
>
> "null primary key encountered in unit of work"
>
> Any help would be much appreciated, I'm really asking if there is a
> better way to do this (persist-find-merge in a transactional EJB
> session bean method doesn't seem to be a good pattern, or at least
> doesn't seem to be working for me!)


Not sure about EJB, but in pure Hibernate I'd use #merge(Object) for
this -- and then work on the returned instance.

HTH,

--
DF.
 
Reply With Quote
 
 
 
 
ses
Guest
Posts: n/a
 
      02-24-2011
On Feb 24, 6:35*pm, Daniele Futtorovic <da.futt.n...@laposte-dot-
net.invalid> wrote:
> On 24/02/2011 15:11, ses allegedly wrote:
>
>
>
>
>
>
>
>
>
> > I assume this must be a fairly common task but I'm struggling to find
> > the best way to achieve this.

>
> > How do you best retrieve the entity you've just persisted with
> > entityManager.persist(myEntity), so that you can then use it in the
> > next part of a transaction.

>
> > I'm referring to an entity for which the container or database manages
> > a generated primary key. Therefore you want to retrieve what you've
> > just persisted so that you can for example establish another
> > relationship - e.g. anotherEntity.add(myEntity) then
> > entityManager.merge(anotherEntity).

>
> > I am trying to do this in a session bean method and carry it out all
> > as one transaction. The way I am retrieving myEntity after persisting
> > is simply selecting the entity with the highest key value (is simple
> > auto increment in MySQL) but there is some problem with this. It
> > retrieves the entity fine with its newly generated key, however when I
> > try to merge it or merge another entity with which I establish a
> > relationship to myEntity I get the following exception:

>
> > "null primary key encountered in unit of work"

>
> > Any help would be much appreciated, I'm really asking if there is a
> > better way to do this (persist-find-merge in a transactional EJB
> > session bean method doesn't seem to be a good pattern, or at least
> > doesn't seem to be working for me!)

>
> Not sure about EJB, but in pure Hibernate I'd use #merge(Object) for
> this -- and then work on the returned instance.
>
> HTH,
>
> --
> DF.


I don't think you can merge in JPA before you've called persist, or do
you mean call merge after persist?
 
Reply With Quote
 
Daniele Futtorovic
Guest
Posts: n/a
 
      02-24-2011
On 24/02/2011 19:40, ses allegedly wrote:
> On Feb 24, 6:35 pm, Daniele Futtorovic<da.futt.n...@laposte-dot-
>>
>> Not sure about EJB, but in pure Hibernate I'd use #merge(Object) for
>> this -- and then work on the returned instance.
>>
>> HTH,
>>

> I don't think you can merge in JPA before you've called persist, or do
> you mean call merge after persist?


As I said, I have only a vague notion of the technology you're
describing, but in Hibernate, the interface of which looks very similar
to this EntityManager, I would use merge _instead of_ (the equivalent
of) persist. #merge is supposed to persist if the entity does not yet
exist, and update it if it does. Merging a 'blank' entity returns me a
(copy of a) persisted entity with the newly assigned identifier set.

--
DF.
 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      02-24-2011
ses wrote:
> Daniele Futtorovic wrote:
>> Not sure about EJB, but in pure Hibernate I'd use #merge(Object) for
>> this -- and then work on the returned instance.

>
> I don't think you can merge in JPA before you've called persist, or do
> you mean call merge after persist?
>


Sure you can. I've done it many times and it's worked.

There are subtleties of the semantics, but you can do it.

--
Lew
 
Reply With Quote
 
Arved Sandstrom
Guest
Posts: n/a
 
      02-24-2011
On 11-02-24 02:40 PM, ses wrote:
> On Feb 24, 6:35 pm, Daniele Futtorovic<da.futt.n...@laposte-dot-
> net.invalid> wrote:
>> On 24/02/2011 15:11, ses allegedly wrote:
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>> I assume this must be a fairly common task but I'm struggling to find
>>> the best way to achieve this.

>>
>>> How do you best retrieve the entity you've just persisted with
>>> entityManager.persist(myEntity), so that you can then use it in the
>>> next part of a transaction.

>>
>>> I'm referring to an entity for which the container or database manages
>>> a generated primary key. Therefore you want to retrieve what you've
>>> just persisted so that you can for example establish another
>>> relationship - e.g. anotherEntity.add(myEntity) then
>>> entityManager.merge(anotherEntity).

>>
>>> I am trying to do this in a session bean method and carry it out all
>>> as one transaction. The way I am retrieving myEntity after persisting
>>> is simply selecting the entity with the highest key value (is simple
>>> auto increment in MySQL) but there is some problem with this. It
>>> retrieves the entity fine with its newly generated key, however when I
>>> try to merge it or merge another entity with which I establish a
>>> relationship to myEntity I get the following exception:

>>
>>> "null primary key encountered in unit of work"

>>
>>> Any help would be much appreciated, I'm really asking if there is a
>>> better way to do this (persist-find-merge in a transactional EJB
>>> session bean method doesn't seem to be a good pattern, or at least
>>> doesn't seem to be working for me!)

>>
>> Not sure about EJB, but in pure Hibernate I'd use #merge(Object) for
>> this -- and then work on the returned instance.
>>
>> HTH,
>>
>> --
>> DF.

>
> I don't think you can merge in JPA before you've called persist, or do
> you mean call merge after persist?


For a good discussion, see
http://blog.xebia.com/2009/03/23/jpa...ched-entities/.
I particularly recommend "The Pattern" section at the bottom. I'd reword
the second piece of advice as

"When updating an existing *managed* entity, we do not invoke any
EntityManager method; the JPA provider will automatically update the
database at flush or commit time."

This ties in better with the third guideline. Main point is, and this is
something that practically all of us have done when starting out with
JPA, you don't need to call merge() or persist() to "save" changes to a
managed entity. That's one of the main reasons we've got the EntityManager.

The persistence specifications (JSR 220 and/or JSR 317) are your
authoritative references. They are very readable specs.

I'm not sure I understand your specific problem. You're in the same
transaction - there's no way in your code of passing the newly-persisted
and now managed entity to the next spot that needs to do something with
it? What I'm saying is, I don't get the "find" part of
persist-find-merge...in fact I'm not even convinced you need the "merge"
in your scenario.

As an aside, it seems you're using IDENTITY as your ID generation
strategy. Is that so?

AHS

--
We must recognize the chief characteristic of the modern era - a
permanent state of what I call violent peace.
-- James D. Watkins
 
Reply With Quote
 
ses
Guest
Posts: n/a
 
      02-25-2011
On Feb 24, 10:06*pm, Arved Sandstrom <asandstrom3min...@eastlink.ca>
wrote:
> On 11-02-24 02:40 PM, ses wrote:
>
>
>
>
>
>
>
>
>
> > On Feb 24, 6:35 pm, Daniele Futtorovic<da.futt.n...@laposte-dot-
> > net.invalid> *wrote:
> >> On 24/02/2011 15:11, ses allegedly wrote:

>
> >>> I assume this must be a fairly common task but I'm struggling to find
> >>> the best way to achieve this.

>
> >>> How do you best retrieve the entity you've just persisted with
> >>> entityManager.persist(myEntity), so that you can then use it in the
> >>> next part of a transaction.

>
> >>> I'm referring to an entity for which the container or database manages
> >>> a generated primary key. Therefore you want to retrieve what you've
> >>> just persisted so that you can for example establish another
> >>> relationship - e.g. anotherEntity.add(myEntity) then
> >>> entityManager.merge(anotherEntity).

>
> >>> I am trying to do this in a session bean method and carry it out all
> >>> as one transaction. The way I am retrieving myEntity after persisting
> >>> is simply selecting the entity with the highest key value (is simple
> >>> auto increment in MySQL) but there is some problem with this. It
> >>> retrieves the entity fine with its newly generated key, however when I
> >>> try to merge it or merge another entity with which I establish a
> >>> relationship to myEntity I get the following exception:

>
> >>> "null primary key encountered in unit of work"

>
> >>> Any help would be much appreciated, I'm really asking if there is a
> >>> better way to do this (persist-find-merge in a transactional EJB
> >>> session bean method doesn't seem to be a good pattern, or at least
> >>> doesn't seem to be working for me!)

>
> >> Not sure about EJB, but in pure Hibernate I'd use #merge(Object) for
> >> this -- and then work on the returned instance.

>
> >> HTH,

>
> >> --
> >> DF.

>
> > I don't think you can merge in JPA before you've called persist, or do
> > you mean call merge after persist?

>
> For a good discussion, seehttp://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-d....
> I particularly recommend "The Pattern" section at the bottom. I'd reword
> the second piece of advice as
>
> "When updating an existing *managed* entity, we do not invoke any
> EntityManager method; the JPA provider will automatically update the
> database at flush or commit time."
>
> This ties in better with the third guideline. Main point is, and this is
> something that practically all of us have done when starting out with
> JPA, you don't need to call merge() or persist() to "save" changes to a
> managed entity. That's one of the main reasons we've got the EntityManager.
>
> The persistence specifications (JSR 220 and/or JSR 317) are your
> authoritative references. They are very readable specs.
>
> I'm not sure I understand your specific problem. You're in the same
> transaction - there's no way in your code of passing the newly-persisted
> and now managed entity to the next spot that needs to do something with
> it? What I'm saying is, I don't get the "find" part of
> persist-find-merge...in fact I'm not even convinced you need the "merge"
> in your scenario.
>
> As an aside, it seems you're using IDENTITY as your ID generation
> strategy. Is that so?
>
> AHS
>
> --
> We must recognize the chief characteristic of the modern era - a
> permanent state of what I call violent peace.
> -- James D. Watkins


Thanks for that link, it is very useful. Because I'm using a detached
entity I think merge will be suitable for what I need.

In actual fact it is a relationship that is causing the error - I have
a structure like this:

User --> Location --> Booking

Where --> depicts a one-to-many unidirectional relationship. I am
trying to persist a new Location (which has zero Bookings), then add
it to a User and merge the User. The problem is the relationship
between Location and Booking - if I remove this relationship (the
field and the get and set from the Location entity) then it works
fine. But obviously I want this relationship to remain so I can in the
future add bookings to the location.

To reiterate, the exception is:

"null primary key encountered in unit of work"

I thought the problem was Location had a null primary key / id after
persisting, but I've proved this not to be the case by logging the id
and it seems clear to me now it is the Location --> Booking
relationship that is the issue.
 
Reply With Quote
 
ses
Guest
Posts: n/a
 
      02-25-2011
On Feb 25, 12:20*pm, ses <stew...@ssims.co.uk> wrote:
> On Feb 24, 10:06*pm, Arved Sandstrom <asandstrom3min...@eastlink.ca>
> wrote:
>
>
>
>
>
>
>
>
>
> > On 11-02-24 02:40 PM, ses wrote:

>
> > > On Feb 24, 6:35 pm, Daniele Futtorovic<da.futt.n...@laposte-dot-
> > > net.invalid> *wrote:
> > >> On 24/02/2011 15:11, ses allegedly wrote:

>
> > >>> I assume this must be a fairly common task but I'm struggling to find
> > >>> the best way to achieve this.

>
> > >>> How do you best retrieve the entity you've just persisted with
> > >>> entityManager.persist(myEntity), so that you can then use it in the
> > >>> next part of a transaction.

>
> > >>> I'm referring to an entity for which the container or database manages
> > >>> a generated primary key. Therefore you want to retrieve what you've
> > >>> just persisted so that you can for example establish another
> > >>> relationship - e.g. anotherEntity.add(myEntity) then
> > >>> entityManager.merge(anotherEntity).

>
> > >>> I am trying to do this in a session bean method and carry it out all
> > >>> as one transaction. The way I am retrieving myEntity after persisting
> > >>> is simply selecting the entity with the highest key value (is simple
> > >>> auto increment in MySQL) but there is some problem with this. It
> > >>> retrieves the entity fine with its newly generated key, however when I
> > >>> try to merge it or merge another entity with which I establish a
> > >>> relationship to myEntity I get the following exception:

>
> > >>> "null primary key encountered in unit of work"

>
> > >>> Any help would be much appreciated, I'm really asking if there is a
> > >>> better way to do this (persist-find-merge in a transactional EJB
> > >>> session bean method doesn't seem to be a good pattern, or at least
> > >>> doesn't seem to be working for me!)

>
> > >> Not sure about EJB, but in pure Hibernate I'd use #merge(Object) for
> > >> this -- and then work on the returned instance.

>
> > >> HTH,

>
> > >> --
> > >> DF.

>
> > > I don't think you can merge in JPA before you've called persist, or do
> > > you mean call merge after persist?

>
> > For a good discussion, seehttp://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-d....
> > I particularly recommend "The Pattern" section at the bottom. I'd reword
> > the second piece of advice as

>
> > "When updating an existing *managed* entity, we do not invoke any
> > EntityManager method; the JPA provider will automatically update the
> > database at flush or commit time."

>
> > This ties in better with the third guideline. Main point is, and this is
> > something that practically all of us have done when starting out with
> > JPA, you don't need to call merge() or persist() to "save" changes to a
> > managed entity. That's one of the main reasons we've got the EntityManager.

>
> > The persistence specifications (JSR 220 and/or JSR 317) are your
> > authoritative references. They are very readable specs.

>
> > I'm not sure I understand your specific problem. You're in the same
> > transaction - there's no way in your code of passing the newly-persisted
> > and now managed entity to the next spot that needs to do something with
> > it? What I'm saying is, I don't get the "find" part of
> > persist-find-merge...in fact I'm not even convinced you need the "merge"
> > in your scenario.

>
> > As an aside, it seems you're using IDENTITY as your ID generation
> > strategy. Is that so?

>
> > AHS

>
> > --
> > We must recognize the chief characteristic of the modern era - a
> > permanent state of what I call violent peace.
> > -- James D. Watkins

>
> Thanks for that link, it is very useful. Because I'm using a detached
> entity I think merge will be suitable for what I need.
>
> In actual fact it is a relationship that is causing the error - I have
> a structure like this:
>
> User --> Location --> Booking
>
> Where --> depicts a one-to-many unidirectional relationship. I am
> trying to persist a new Location (which has zero Bookings), then add
> it to a User and merge the User. The problem is the relationship
> between Location and Booking - if I remove this relationship (the
> field and the get and set from the Location entity) then it works
> fine. But obviously I want this relationship to remain so I can in the
> future add bookings to the location.
>
> To reiterate, the exception is:
>
> "null primary key encountered in unit of work"
>
> I thought the problem was Location had a null primary key / id after
> persisting, but I've proved this not to be the case by logging the id
> and it seems clear to me now it is the Location --> Booking
> relationship that is the issue.


I think I have now resolved the issue, it was simply that I hadn't
added the @GeneratedValue annotation to the id columns with
@GeneratedValue(GenerationStrategy.IDENTITY)

I didn't realise this was required in order for the persistence
manager to retrieve the ID in the case that the database generates it
(rather than the container).
 
Reply With Quote
 
Arved Sandstrom
Guest
Posts: n/a
 
      02-25-2011
On 11-02-25 10:47 AM, ses wrote:
[ SNIP ]

> I think I have now resolved the issue, it was simply that I hadn't
> added the @GeneratedValue annotation to the id columns with
> @GeneratedValue(GenerationStrategy.IDENTITY)
>
> I didn't realise this was required in order for the persistence
> manager to retrieve the ID in the case that the database generates it
> (rather than the container).


That's sort of why I asked whether you were using IDENTITY; I had my
suspicions as soon as you mentioned "null primary key".

http://en.wikibooks.org/wiki/Java_Pe...nce_Strategies
is a decent discussion. You'll note upon reading here, that if you're
using IDENTITY it has some things to look out for, one of them being
that you won't have an ID until after you flush or commit.

Not having a @GeneratedValue at all is OK, which is what you started out
with. One app I help maintain has a few audit-type entities set up this
way; the @Id values are GUIDs created in a @PrePersist method. One way
or the other, either by the application or by a @GeneratedValue, you
obviously have to set (or have set) the ID somehow.

AHS
--
We must recognize the chief characteristic of the modern era - a
permanent state of what I call violent peace.
-- James D. Watkins
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Possible to generate "ejb-jar.xml" from EJB class (source)? "ejb-jar.xml" appserver independent? Raymond Schanks Java 0 08-03-2010 08:21 AM
Entity Framework - Reassigning child entity's parent Norm ASP .Net 3 07-06-2009 07:28 PM
How to relate a SQL based entity with an Object based entity in Entity Framework markla ASP .Net 1 10-06-2008 09:42 AM
Managing two persisted versions of the same entity (preview vs live)in Hibernate. Daniel Pitts Java 0 11-14-2007 07:53 PM
Entity Name or Entity Number? Samuel van Laere HTML 4 02-24-2007 10:11 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57