Hi,
1. Reconfirmed the error.
2. Found no related issue in OpenJPA JIRA.
3. The following patch can be applied to fix it.
Index:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java
===================================================================
---
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java
(revision 618739)
+++
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/EmbedFieldStrategy.java
(working copy)
@@ -165,7 +165,8 @@
FieldMapping[] fields =
field.getEmbeddedMapping().getFieldMappings();
for (int i = 0; i < fields.length; i++)
if (!Boolean.TRUE.equals(fields[i].isCustomInsert(em, store)))
- fields[i].insert(em, store, rm);
+ if (!fields[i].isPrimaryKey())
+ fields[i].insert(em, store, rm);
if (field.getColumnIO().isInsertable(0, true))
setNullIndicatorColumn(sm, row);
Cedric Hurst wrote:
>
> I'm not sure if this is a genuine bug or if I'm doing something wrong, but
> I thought I'd check here before I open a JIRA.
>
> BaseEntity is a @MappedSuperclass which holds only an id property
> Address is an @Entity which extends BaseAddress and holds values for
> streetAddress, city, state, zip. It also has a property called geocode
> which is an @Embedded type (see next)
> Geocode is an @Embeddable which is embedded inside Address and holds
> values for the latitude and longitude values
>
> Go here to see the actual code for the JPA objects:
>
> http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/OpenJPA/EmbeddableTest/src/entity
>
> Now, in my test java application, I attempt to create a new Address
> providing values for streetAddress, city, state, zip but not specifying
> anything for geocode:
>
> http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/OpenJPA/EmbeddableTest/src/runtime/JpaTest.java?rev=32
>
> When I attempt to persist this Address object, I get an
> InvalidStateException. Here is the log:
>
> 47 CustomerTest INFO [main] openjpa.Runtime - Starting OpenJPA
> 1.1.0-SNAPSHOT
> 156 CustomerTest INFO [main] openjpa.jdbc.JDBC - Using dictionary
> class "org.apache.openjpa.jdbc.sql.DerbyDictionary".
> 1469 CustomerTest WARN [main] openjpa.MetaData - No setter was found
> for method longtitude in type entity.Geocode while searching for
> persistent properties. This method will be ignored. If you intended for
> this to be persistent, please add a corresponding setter, or switch to
> field access for this type hierarchy.
> 1484 CustomerTest WARN [main] openjpa.MetaData - No setter was found
> for method longtitude in type entity.Geocode while searching for
> persistent properties. This method will be ignored. If you intended for
> this to be persistent, please add a corresponding setter, or switch to
> field access for this type hierarchy.
> 1656 CustomerTest INFO [main] openjpa.Enhance - Creating subclass for
> "[class entity.Address, class entity.Geocode, class entity.BaseEntity]".
> This means that your application will be less efficient and will consume
> more memory than it would if you ran the OpenJPA enhancer. Additionally,
> lazy loading will not be available for one-to-one and many-to-one
> persistent attributes in types using field access; they will be loaded
> eagerly instead.
> 1703 CustomerTest WARN [main] openjpa.MetaData - No setter was found
> for method longtitude in type entity.Geocode while searching for
> persistent properties. This method will be ignored. If you intended for
> this to be persistent, please add a corresponding setter, or switch to
> field access for this type hierarchy.
> 1719 CustomerTest WARN [main] openjpa.MetaData - No setter was found
> for method longtitude in type entity.Geocode while searching for
> persistent properties. This method will be ignored. If you intended for
> this to be persistent, please add a corresponding setter, or switch to
> field access for this type hierarchy.
> 1766 CustomerTest WARN [main] openjpa.MetaData - No setter was found
> for method longtitude in type entity.Geocode while searching for
> persistent properties. This method will be ignored. If you intended for
> this to be persistent, please add a corresponding setter, or switch to
> field access for this type hierarchy.
> 1891 CustomerTest TRACE [main] openjpa.jdbc.SQL - <t 1090273532, conn
> 1509972480> executing prepstmnt 1293569306 SELECT SEQUENCE_VALUE FROM
> OPENJPA_SEQUENCE_TABLE WHERE ID = ? FOR UPDATE WITH RR [params=(int) 0]
> 1891 CustomerTest TRACE [main] openjpa.jdbc.SQL - <t 1090273532, conn
> 1509972480> [0 ms] spent
> 1891 CustomerTest TRACE [main] openjpa.jdbc.SQL - <t 1090273532, conn
> 1509972480> executing prepstmnt 559423832 UPDATE OPENJPA_SEQUENCE_TABLE
> SET SEQUENCE_VALUE = ? WHERE ID = ? AND SEQUENCE_VALUE = ? [params=(long)
> 901, (int) 0, (long) 851]
> 1906 CustomerTest TRACE [main] openjpa.jdbc.SQL - <t 1090273532, conn
> 1509972480> [15 ms] spent
> 2000 CustomerTest TRACE [main] openjpa.jdbc.SQL - <t 1090273532, conn
> 1181632110> executing prepstmnt 1721001620 INSERT INTO Address (id, city)
> VALUES (?, ?) [params=(long) 851, (String) Chicago]
> 2000 CustomerTest TRACE [main] openjpa.jdbc.SQL - <t 1090273532, conn
> 1181632110> [0 ms] spent
> Exception in thread "main" <openjpa-1.1.0-SNAPSHOT-r420667:616905 fatal
> store error> org.apache.openjpa.persistence.RollbackException: The
> transaction has been rolled back. See the nested exceptions for details
> on the errors that occurred.
> at
> org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:494)
> at runtime.JpaTest.main(JpaTest.java:24)
> Caused by: <openjpa-1.1.0-SNAPSHOT-r420667:616905 fatal general error>
> org.apache.openjpa.persistence.PersistenceException: The transaction has
> been rolled back. See the nested exceptions for details on the errors
> that occurred.
> at
> org.apache.openjpa.kernel.BrokerImpl.newFlushException(BrokerImpl.java:2145)
> at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1992)
> at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:1890)
> at
> org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:1808)
> at
> org.apache.openjpa.kernel.LocalManagedRuntime.commit(LocalManagedRuntime.java:81)
> at org.apache.openjpa.kernel.BrokerImpl.commit(BrokerImpl.java:1332)
> at
> org.apache.openjpa.kernel.DelegatingBroker.commit(DelegatingBroker.java:861)
> at
> org.apache.openjpa.persistence.EntityManagerImpl.commit(EntityManagerImpl.java:483)
> ... 1 more
> Caused by: <openjpa-1.1.0-SNAPSHOT-r420667:616905 fatal user error>
> org.apache.openjpa.persistence.InvalidStateException: Attempt to set
> column "Address.id" to two different values: (class java.lang.Long)"851",
> (null)"null" This can occur when you fail to set both sides of a two-sided
> relation between objects, or when you map different fields to the same
> column, but you do not keep the values of these fields in synch.
> at org.apache.openjpa.jdbc.sql.PrimaryRow.setObject(PrimaryRow.java:338)
> at org.apache.openjpa.jdbc.sql.RowImpl.setNull(RowImpl.java:456)
> at
> org.apache.openjpa.jdbc.meta.strats.EmbedFieldStrategy$EmbeddedRow.setNull(EmbedFieldStrategy.java:1400)
> at
> org.apache.openjpa.jdbc.meta.strats.HandlerStrategies.set(HandlerStrategies.java:136)
> at
> org.apache.openjpa.jdbc.meta.strats.HandlerStrategies.set(HandlerStrategies.java:93)
> at
> org.apache.openjpa.jdbc.meta.strats.HandlerFieldStrategy.insert(HandlerFieldStrategy.java:126)
> at
> org.apache.openjpa.jdbc.meta.FieldMapping.insert(FieldMapping.java:562)
> at
> org.apache.openjpa.jdbc.meta.strats.EmbedFieldStrategy.insert(EmbedFieldStrategy.java:168)
> at
> org.apache.openjpa.jdbc.meta.strats.EmbedFieldStrategy.insert(EmbedFieldStrategy.java:147)
> at
> org.apache.openjpa.jdbc.meta.FieldMapping.insert(FieldMapping.java:562)
> at
> org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.insert(AbstractUpdateManager.java:203)
> at
> org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.populateRowManager(AbstractUpdateManager.java:145)
> at
> org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:85)
> at
> org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:72)
> at
> org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:549)
> at
> org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:130)
> ... 8 more
>
> I've tested a few permutations and this is what I've found:
>
> ===
>
> If I try to set geocode values for the Address object before persisting...
>
> http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/OpenJPA/EmbeddableTest/src/runtime/JpaTest.java?rev=29
>
> ... the address object still fails to persist.
>
> ===
>
> If I remove the Address.geocode embedded object...
>
> http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/OpenJPA/EmbeddableTest/src/entity/Address.java?rev=31
>
> ... the address object persists successfully.
>
> ===
>
> If I change the Address class so it does not extend BaseEntity (and
> instead provides its own @Id property)...
>
> http://trac2.assembla.com/d5Z24gWSer3lvHabIlDkbG/browser/OpenJPA/EmbeddableTest/src/entity/Address.java?rev=30
>
> ...the address object persists successfully
>
> ===
>
> Thus, it seems to be an issue specifically related to the pattern of an
> @Embeddable object inside an @Entity which extends a @MappedSuperclass.
>
> I've tested this out on both openjpa-1.1.0-SNAPSHOT and openjpa-1.0.0.
>
--
View this message in context:
http://www.nabble.com/Problem-with-MappedSuperclass-Entity-Embeddable-object-graph-tp15298457p15299690.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.