2016-09-23 3 views
0

나는 코드의이 비트와 함께 DB에 저장됩니다 JPA 엔티티 새로운 (데이터베이스 아직에 즉 존재하지 않는)가 개체에 다른 값을 채우고 ID가 DB에 생성됩니다.는 OpenJPA는 불규칙

엔티티는 다음과 같습니다

@Entity 
public class Fund extends AbstractFund implements Serializable 
{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column(name = "fundId") 
    protected Long id; 

    // other fields and getters etc. 

} 

AbstractFund 더 필드가 추상적 인 매핑 된 슈퍼 클래스입니다.

데이터베이스의 테이블에는 ID로 정의 된 fundId 열이 있습니다. 이것은 오랫동안 정상적으로 작동했습니다. 그러나 flush이 호출되면 간헐적 인 오류가 발생합니다. 배포 후 코드는 잠시 동안 잘 작동하고 갑자기이 예외 던지기 시작 :이 다른 환경에서 재현 할 수 없었와는 OpenJPA가 갑자기을 삽입하려고 시작하는 이유에 관해서는 딱하다 한

Caused by: <openjpa-2.3.0-r422266:1540826 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. 
FailedObject: [email protected] 
     at org.apache.openjpa.kernel.BrokerImpl.newFlushException(BrokerImpl.java:2370) [openjpa-all-2.3.0.jar:2.3.0] 
     at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2207) [openjpa-all-2.3.0.jar:2.3.0] 
     at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2105) [openjpa-all-2.3.0.jar:2.3.0] 
     at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1876) [openjpa-all-2.3.0.jar:2.3.0] 
     at org.apache.openjpa.kernel.DelegatingBroker.flush(DelegatingBroker.java:1045) [openjpa-all-2.3.0.jar:2.3.0] 
     at org.apache.openjpa.persistence.EntityManagerImpl.flush(EntityManagerImpl.java:663) [openjpa-all-2.3.0.jar:2.3.0] 
     at org.jboss.as.jpa.container.AbstractEntityManager.flush(AbstractEntityManager.java:457) [wildfly-jpa-8.1.0.Final.jar:8.1.0.Final] 
     ...... 
Caused by: java.lang.Exception: <openjpa-2.3.0-r422266:1540826 fatal store error> org.apache.openjpa.persistence.EntityExistsException: 
Cannot insert explicit value for identity column in table 'Fund' when IDENTITY_INSERT is set to OFF. {prepstmnt 2128975916 INSERT INTO Fund 
(fundId, ... other columns ...) VALUES (?, ?, ?,)} [code=544, state=23000] 
FailedObject: [email protected] 
     at org.apache.openjpa.util.Exceptions.replaceNestedThrowables(Exceptions.java:255) [openjpa-all-2.3.0.jar:2.3.0] 
     at org.apache.openjpa.persistence.PersistenceException.writeObject(PersistenceException.java:100) [openjpa-all-2.3.0.jar:2.3.0] 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.7.0_60] 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [rt.jar:1.7.0_60] 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [rt.jar:1.7.0_60] 
     at java.lang.reflect.Method.invoke(Method.java:606) [rt.jar:1.7.0_60] 
     at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:271) 
     at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:290) 
     at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:245) 
     at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:125) 
     at org.jboss.marshalling.cloner.SerializingCloner.cloneFields(SerializingCloner.java:341) 
     at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:293) 
     at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:277) 
     at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:277) 
     at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:277) 
     at org.jboss.marshalling.cloner.SerializingCloner.initSerializableClone(SerializingCloner.java:277) 
     at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:245) 
     at org.jboss.marshalling.cloner.SerializingCloner.clone(SerializingCloner.java:125) 
     at org.jboss.as.ejb3.remote.LocalEjbReceiver.clone(LocalEjbReceiver.java:314) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final] 
     at org.jboss.as.ejb3.remote.LocalEjbReceiver.clone(LocalEjbReceiver.java:297) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final] 
     at org.jboss.as.ejb3.remote.LocalEjbReceiver.processInvocation(LocalEjbReceiver.java:249) [wildfly-ejb3-8.1.0.Final.jar:8.1.0.Final] 
     ... 126 more 

을 식별 컬럼에 대한 값.

OpenJPA 버전 2.3.0을 사용하고 있습니다.

버전 2.4.1로 업데이트하려고했지만 문제가 계속됩니다.

+0

나는 테이블'Fund' 이미 문제를 일으키는 오래된 행이있는 경우 의심? –

+0

가능성은 희박합니다 - SQL 오류는 ID 열 삽입과 관련하여 매우 구체적입니다. –

+1

오류는 명백합니다. ID 필드에 값을 삽입 할 수 없다는 내용입니다. ID 필드가 이미 설정된 엔터티에 병합을 호출하고 있습니다. 이 예외가 발생하면 병합 중 무엇이고 SQL 삽입을 시도하여 삽입/업데이트/삭제를 볼 수 있으므로이 문제가 발생한 이유를 추적 할 수 있습니다. 내 생각 엔 엔티티를 삭제하고이를 다시 병합하려고 시도하고 있으며 ID 필드가 당신을 허용하지 않을 것입니다. – Chris

답변

-1

먼저 개체를 검색 한 다음 새 개체를 만들고 검색된 개체의 개체를 새 개체로 복사 한 다음 새 개체의 persist 메서드를 호출해야합니다. BeanUtils.copyProperties 메서드를 사용하여 원본 개체의 속성을 대상 개체로 복사하거나 직접 개체 개체에서 복사 할 수 있습니다.

+0

개체가 새롭다는 것이 명확하지 않아 DB에 존재하지 않습니다. –

2

첫째, 모든 존경심으로, 나는 Prashant Katara가 그의 대답으로 어디로 가고 있는지 확실하지 않습니다. 나는 당신이 select/copy/persist를 할 필요가있는 시나리오를 모른다. ?? Chris는 좋은 의견을 제시했습니다. 이 문제가 어떻게 발생했는지 정확히 말할 수는 없지만, 문제를 일으킬 수있는 방법에 대해 알려주도록하겠습니다. 그런 다음 진술

public void save(Fund entity) { 
    em.merge(entity); 
    em.flush(); 
} 

는 "우리는 ID를 사용하기 때문에 우리는 ..... 플러시 필요"당신의 설명에서이 '저장'방법을 기록했다. 여기에 관련된 것들이 몇 가지 있습니다. 보시다시피, 전달 된 '엔터티'를 병합합니다. 그러나 'em.merge'에서 반환 된 객체는 반환하지 않습니다. OpenJPA는 'entity'의 id를 채우지 않을 것입니다. merge가 반환 한 id 값만 채 웁니다! 사람들은 병합에 전달 된 인스턴스가 관리되는 인스턴스가 아니라는 사실을 항상 잊어 버립니다! 병합에서 반환 된 인스턴스가 관리됩니다! 당신이 이드의 가치를 필요로한다고 말했기 때문에 실제로 저장 호출 후에 '엔티티'를 사용하고있는 것으로 가정하므로 관리되는 인스턴스 (예 : 'em.merge'가 반환 한 인스턴스)를 사용해야합니다. 이것은 안전한 작업은 아니며, 플러시 후에도 fundId에 대한 getter 메서드를 호출하면 'null'이 표시되지 않는다는 것에 놀랍니다. 절대로 반복하지 않는다면, 호출 후에 'entity'를 사용하면 저장 방법이 괜찮을 것입니다. 이 기업은 저장 후 계속 사용하려는 경우, 다음은 다음과 같이한다 저장 :

public Fund save(Fund entity) { 
    Fund entityPrime = em.merge(entity); 
    em.flush(); 
    return entityPrime; 
} 

마지막으로는 OpenJPA는 식별 필드에 대한 필드/열을 포함하는 INSERT를 발행하지 않습니다. 그래서 당신은 펀드가 삽입 된 INSERT를 보지 말아야합니다.INSERT에 기금이 들어있는 경우에 어떻게 도달 했는가하는 것입니다. '@GeneratedValue (strategy = GenerationType.IDENTITY)'가 포함되지 않은 클래스 패스 어딘가에 이전 버전의 Fund가있을 수 있습니다. INSERT 작업의 일부로 IDENTIFICATION 값이 데이터베이스에서 반환되고 OpenJPA는 반환 된 값을 (관리 된) IDENTIFICATION 필드에 할당합니다.

감사합니다,

히스

+0

감사합니다 히스, 당신이 말하는 것은 의미가 있습니다. 나는 우리가 펀드 삽입을 보지 말아야한다는 것에 동의합니다. 붙여 넣은 코드에서 실수를했습니다. 우리는 엔티티를'merge' 메쏘드에서 반환 된 값으로 설정합니다. –

+0

Ok Sean, 업데이트 된 코드에서 여전히 동일한 문제가 발생합니다 (예 : 병합에서 반환 한 인스턴스 사용). 그렇다면 내가이 밑바닥까지 도달 할 수있는 유일한 방법은 전체 엔터티와 유스 케이스의 스 니펫을 첨부 (또는 붙여 넣기)하는 것입니다. Tx가 언제 사용되는지 알고 싶습니다. 시작/커밋 및 병합/플러시 (해당 항목에 대한 모든 entitymanager 호출). 또한 Fund.class에 대한 전체 클래스 경로를 검색 할 것을 제안합니다. 문제의 산발적 인 (또는 env 특정) 특성을 제공합니다. OpenJPA가 fundId가 IDENTITY가 아니라고 생각하는 오래된 메타 데이터를 찾을 수 있는지 궁금합니다. –