Re: How to get generated keys without requerying the database?

2011-01-25 Thread Jeremy Bauer
Hi,

Based on the code snippets you've provided, it looks like you my just either
need to call em.flush() to force the DB update or commit the transaction
before getting the recId from the dto.  If that doesn't help, repost and
I'll dig a little deeper.  OpenJPA refreshes primary key identity fields
after a flush or commit.  I think it will/should do the same for non-PK
generated fields.

hth,
-Jeremy

On Mon, Jan 24, 2011 at 8:33 PM, robsinner robsin...@yahoo.com wrote:


 I have an Entity with a non primary key identity column.

 This entity
 Part.java
 has the following fields among others

@EmbeddedId
private PartPK pk;


@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name=REC_ID)
private Integer recId;

 Note the EmbeddedId does not contain the  Generated Value , the PartPk is
 made up of two strings, one for company and one for part number.

 So the Entity has a primary key which is  a business composite key. This
 table also has a column in DB2 which is a IDENTITY column which is not part
 of the primary key. This identity column which is not part of the primary
 key is called REC_ID.

 After insert I would like the recId to be populated onto the entity however
 it is not. In JDBC this is usually accomplished via
 statement.getGeneratedKeys after the insert statements has been run.

 For example in a straight JDBC Data Access Object this would be
 accomplished
 after the insert statement by
// retrieve values from auto-increment columns
rs = stmt.getGeneratedKeys();
if (rs != null  rs.next()) {
dto.setRecId( new Integer( rs.getInt(1) ) );
}

 However when I run a junit test using a simple JPA data access object the
 recId column is null after insert.

public void testInsert()
{
log.info(insert);
log.info(part=+part);

manager = getManager();

pk.setIncomp(comp);
pk.setInpart(part);

dto.setPk(pk);

log.info(dto);
manager.insert(dto);

log.info(recId=+dto.getRecId());
assertFalse(recId is null after insert should not
 be, dto.getRecId() ==
 null); //fails here
  }


 The manager class is wrapping this data access object code

public PK insert(DTO dto) throws Exception {
EntityManager em = getEntityManager();
em.persist(dto);
return dto.getPk();
}

 How do I specify the mapping in the entity with a non primary key identity
 column such that after an insert the non primary key identity column is
 populated onto the entity.

 Among other things I am using Db2 with spring and openjpa 2.2.0.

 I believe this has something to do with getGeneratedKeys and how I'm doing
 the mapping in the entity and possibly DB2 with openjpa.

 The table are legacy and are not easily modifiable to accomplish this. Im
 trying to avoid having to relook up the non primary key with a seperate
 query by the primary key after the insert.

 Thank you in advance for your assistance. I searched in the nabble users
 list and could not find anything related. If you need more detailed
 information I can post more. I believe this is a simple configuration done
 incorrectly at the entity level.

 Thank you in advance for any assistance you provide.
 --
 View this message in context:
 http://openjpa.208410.n2.nabble.com/How-to-get-generated-keys-without-requerying-the-database-tp5957346p5957346.html
 Sent from the OpenJPA Users mailing list archive at Nabble.com.



Re: How to get generated keys without requerying the database?

2011-01-25 Thread robsinner

Thanks so much for your quick response. I really appreciate it.

I tried adding the em.flush after the em.persist and I am still getting the
same behavior i.e. 
After the insert the dto.recId which is mapped to an non primary key
IDENTITY column is not populated on the DTO 
although the REC_ID exists in the database. 

I dont know of course but this would lead me to believe that at the lower
level 
stmt.getGeneratedKeys is not getting called to populate non primary key
IDENTITY Fields

I will attempt to post more  detailed information in the hopes that will
help and not confuse the issue.

The Entity/DTO called INPARTMASTER actually not PART
code
/**
 * The persistent class for the INPARTMASTER database table.
 * 
 */
@Entity
@Table(name=INPARTMASTER)
public class Inpartmaster implements Serializable,
PersistentInpartmasterPK {
private static final long serialVersionUID = 1L;

@EmbeddedId
private InpartmasterPK pk;

... more columns here

@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name=REC_ID)
private Integer recId;

... more columns here
/code

InpartmasterPK
code
package com.ais.persistence.entities;

import java.io.Serializable;
import javax.persistence.Embeddable;

@Embeddable
public class InmasterPK implements Serializable {
private String incomp;

private String inindiv;

private String inpart;

private static final long serialVersionUID = 1L;

public InmasterPK() {
super();
}

getters/setters etc.

}

/code


For The Data Access Object Code
The DAO is Spring @Transactional  Beans. The annotation for the DAO is 
@Transactional(propagation = Propagation.REQUIRED, isolation =
Isolation.DEFAULT, rollbackFor = { Exception.class })

code
public PK insert(DTO dto) throws Exception {
EntityManager em = getEntityManager();
em.persist(dto);
em.flush();//added to try and retrieve stmt.getGeneratedKeys
return dto.getPk();
}
/code

I have a Manager class which wraps the DAO. This manager is also
transactional with this annotation
@Transactional(propagation = Propagation.REQUIRED, isolation =
Isolation.DEFAULT, rollbackFor = { Exception.class })

The Manager code at this point simply wraps the DAO code
code
public Inpartmaster insert(Inpartmaster inpartmaster) throws
InventoryException {

InpartmasterPK pk = null;
try {
//TODO: add Pre-submit validation process

//Calling JPA InpartmasterDao

pk = inpartmasterDao.insert(inpartmaster);
} 
catch (Exception e) {
log.error(Utility.getStackTrace(e));
log.error(e);
throw new InventoryException(e);
}

return inpartmaster;
}
/code 

The junit code looks like 
code

public void testInsert() 
{
try {
log.info(insert);
log.info(part=+part);

manager = getManager();

pk.setIncomp(comp);
pk.setInpart(part);

dto.setPk(pk);

log.info(dto);
dto.setChgdate(new Date());
manager.insert(dto);

log.info(recId=+dto.getRecId());
assertFalse(recId is null after insert should not be, 
dto.getRecId() ==
null); //fails here the recId is not being populated with something like
stmt.getGeneratedKeys

}
catch(Exception e)
{
log.error(---);
log.error(Utility.getStackTrace(e));
fail(e.getMessage());   
}
}


/code
The persistence.xml looks like
code

?xml version=1.0 encoding=UTF-8?
persistence xmlns=http://java.sun.com/xml/ns/persistence; 
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance; 
version=2.0 
xsi:schemaLocation=http://java.sun.com/xml/ns/persistence 

http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd;
persistence-unit name=airweb-JPA-J2-SNAPSHOT
transaction-type=RESOURCE_LOCAL

providerorg.apache.openjpa.persistence.PersistenceProviderImpl/provider
jta-data-sourcejdbc/db2svr/jta-data-source
classcom.ais.persistence.entities.InpartmasterPK/class
classcom.ais.persistence.entities.Inpartmaster/class


Re: How to get generated keys without requerying the database?

2011-01-25 Thread robsinner

Kevin, 

Thanks for your response.

I am including the full log from my junit test with TRACE turned on via
openjpa.Log in persistence.xml
property name=openjpa.Log value=DefaultLevel=WARN, Runtime=TRACE,
Tool=INFO, SQL=TRACE/

I am using the DB2Dictionary in my persistence.xml

property name=openjpa.jdbc.DBDictionary
value=org.apache.openjpa.jdbc.sql.DB2Dictionary/

I have a junit test which prints out these two variables from the
DB2Dictionary.

public void testShowDb2Dictionary()
{
DB2Dictionary dictionary = new
org.apache.openjpa.jdbc.sql.DB2Dictionary();

log.info(dictionary.lastGeneratedKeyQuery=+dictionary.lastGeneratedKeyQuery);
//this shows VALUES(IDENTITY_VAL_LOCAL())

log.info(dictionary.supportsGetGeneratedKeys=+dictionary.supportsGetGeneratedKeys);
//this shows null
}

This prints out 
2011-01-25 10:27:06,266 INFO  [] com.ais.persistence.InpartmasterTest:103 -
dictionary.lastGeneratedKeyQuery=VALUES(IDENTITY_VAL_LOCAL())
2011-01-25 10:27:06,266 INFO  [] com.ais.persistence.InpartmasterTest:104 -
dictionary.supportsGetGeneratedKeys=null

I would think the DB2Dictionary.supportsGetGeneratedKeys ==null is part of
the problem. But I dont know how to resolve.

I know I am able to use stmt.getGeneratedKeys with the same db2 jdbc driver
class (p:driverClass=com.ibm.db2.jcc.DB2Driver) 
with a straight JDBC Dao Framework
 
Thank you for your help.

Full Log Below

2011-01-25 10:26:55,861 INFO  []
com.cms.shared.ext.firestorm.FirestormUtil:81 - FirestormUtil static init
loading spring 
2011-01-25 10:26:55,876 INFO  []
com.cms.shared.ext.firestorm.FirestormUtil:122 - applicationContext.xml
exists=true
2011-01-25 10:26:55,878 INFO  []
com.cms.shared.ext.firestorm.FirestormUtil:126 -
URL=file:/C:/RAD/aircore-JPA-J2-SNAPSHOT/target/classes/applicationContext.xml
2011-01-25 10:26:55,879 INFO  []
com.cms.shared.ext.firestorm.FirestormUtil:135 - running with
applicationContext.xml
2011-01-25 10:26:55,880 INFO  []
com.cms.shared.ext.firestorm.FirestormUtil:122 - applicationContext2.xml
exists=true
2011-01-25 10:26:55,881 INFO  []
com.cms.shared.ext.firestorm.FirestormUtil:126 -
URL=file:/C:/RAD/aircore-JPA-J2-SNAPSHOT/target/classes/applicationContext2.xml
2011-01-25 10:26:55,882 INFO  []
com.cms.shared.ext.firestorm.FirestormUtil:135 - running with
applicationContext2.xml
2011-01-25 10:26:55,883 INFO  []
com.cms.shared.ext.firestorm.FirestormUtil:122 - applicationContext3.xml
exists=false
2011-01-25 10:26:55,884 ERROR []
com.cms.shared.ext.firestorm.FirestormUtil:130 - class path resource
[applicationContext3.xml] cannot be resolved to URL because it does not
exist
2011-01-25 10:26:55,886 ERROR []
com.cms.shared.ext.firestorm.FirestormUtil:139 - running without
applicationContext3.xml
2011-01-25 10:26:55,912 INFO  []
com.cms.shared.ext.firestorm.FirestormUtil:101 - building Spring
ClassPathXmlApplicationContext from these files[applicationContext.xml
applicationContext2.xml]
2011-01-25 10:26:55,957 INFO  []
org.springframework.context.support.ClassPathXmlApplicationContext:456 -
Refreshing
org.springframework.context.support.ClassPathXmlApplicationContext@4998a455:
startup date [Tue Jan 25 10:26:55 PST 2011]; root of context hierarchy
2011-01-25 10:26:56,013 INFO  []
org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315 - Loading
XML bean definitions from class path resource [applicationContext.xml]
2011-01-25 10:26:56,417 INFO  []
org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315 - Loading
XML bean definitions from class path resource [jpapersistence.xml]
2011-01-25 10:26:56,669 INFO  []
org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315 - Loading
XML bean definitions from class path resource [stdcore.xml]
2011-01-25 10:26:59,331 INFO  []
org.springframework.beans.factory.xml.XmlBeanDefinitionReader:315 - Loading
XML bean definitions from class path resource [applicationContext2.xml]
2011-01-25 10:26:59,384 INFO  []
org.springframework.beans.factory.support.DefaultListableBeanFactory:618 -
Overriding bean definition for bean 'fiscalYrDao': replacing [Generic bean:
class [com.cms.shared.gen.firestorm.jdbc.FiscalYrDaoImpl]; scope=;
abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0;
autowireCandidate=true; primary=false; factoryBeanName=null;
factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined
in class path resource [stdcore.xml]] with [Generic bean: class
[com.cms.shared.gen.firestorm.jdbc.FiscalYrDaoImpl]; scope=; abstract=false;
lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true;
primary=false; factoryBeanName=null; factoryMethodName=null;
initMethodName=null; destroyMethodName=null; defined in class path resource
[applicationContext2.xml]]
2011-01-25 10:26:59,392 INFO  []
org.springframework.beans.factory.support.DefaultListableBeanFactory:618 -
Overriding bean definition for bean 'aircraftDao': replacing [Generic 

Re: How to get generated keys without requerying the database?

2011-01-25 Thread robsinner

DB2 (from Control Center Help About)
Product Identifier SQL09072
Level Identifier 08030107
Level DB2 v9.7.200.358
Build Level s100514
PTF IP23084

JCC Driver is db2jcc4-9.7.100.177.jar, db2jcc_license_cu-9.7.100.177.jar

Thank you for your help,

R
S
-- 
View this message in context: 
http://openjpa.208410.n2.nabble.com/How-to-get-generated-keys-without-requerying-the-database-tp5957346p5960442.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.


Re: How to get generated keys without requerying the database?

2011-01-25 Thread robsinner

Jeremy (and Kevin), 

Thank you so much for your quick turnaround time and response and the
workaround. 

I modified the persistence.xml with 

I also created a bug in JIRA- My first one so I hope that it was detailed
enough. 
https://issues.apache.org/jira/browse/OPENJPA-1930

Thanks again, it is much appreciated.

R
S
-- 
View this message in context: 
http://openjpa.208410.n2.nabble.com/How-to-get-generated-keys-without-requerying-the-database-tp5957346p5960986.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.