# JPA Mapping von 1:n Beziehung (ORA-01400)



## Malk (22. Juli 2010)

Ich habe da ein Problem, dass mich zur Verzweiflung treibt... ich möchte eine 1:n Beziehung bauen, die bidirektional ist. Leider bekomme ich immer eine Fehlermeldung.
Ich habe schon massig gesucht, finde aber keine Lösung für mein Problem.
Vielleicht kann mir hier ja jemand helfen.

Sonstiges: Spring 3.0.3 Core & Oracle XE

Dies ist die eine Klasse (NUTZER):

```
...
@Entity
@Table(name="NUTZER")
public class Nutzer implements Serializable{
	
	private static final long serialVersionUID = 377116682345615499L;
	
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column (name="NUTZER_ID")
	private Long id;
	
         ...
	
	//Assoziationen


	@OneToMany (cascade=CascadeType.ALL)
	private List<Teilnahme> dieTeilnahmen;
	
	
	// LEER-KONSTRUKTOR
	public Nutzer(){}
        ...
```

und das hier die andere (TEILNAHMEN):

```
@Entity
@Table(name="TEILNAHME")
public class Teilnahme implements Serializable{

	private static final long serialVersionUID = 611686689346616496L;
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	@Column (name="TEILN_ID")
	private Long id;
	
	
	//Assoziationen
	
	@ManyToOne
	@JoinColumn(name = "nutzer_id", nullable = false, insertable=false, updatable=false)
	private Nutzer nutzer;

	

	//LEER-KONSTRUKTOR
	public Teilnahme(){}

...
```

Als Fehlerstack bekomme ich:

```
javax.persistence.EntityExistsException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
	at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:604)
	at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:73)
	at com.adesso.schuva.logik.repositories.impl.NutzerRepositoryImpl.getAlleNutzer(NutzerRepositoryImpl.java:42)
	at com.adesso.schuva.test.Test01.testOlli00(Test01.java:84)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.springframework.test.context.junit4.SpringTestMethod.invoke(SpringTestMethod.java:163)
	at org.springframework.test.context.junit4.SpringMethodRoadie.runTestMethod(SpringMethodRoadie.java:233)
	at org.springframework.test.context.junit4.SpringMethodRoadie$RunBeforesThenTestThenAfters.run(SpringMethodRoadie.java:333)
	at org.springframework.test.context.junit4.SpringMethodRoadie.runWithRepetitions(SpringMethodRoadie.java:217)
	at org.springframework.test.context.junit4.SpringMethodRoadie.runTest(SpringMethodRoadie.java:197)
	at org.springframework.test.context.junit4.SpringMethodRoadie.run(SpringMethodRoadie.java:143)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.invokeTestMethod(SpringJUnit4ClassRunner.java:142)
	at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
	at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
	at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
	at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
	at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
	at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
	at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:237)
	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
	at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
	at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:41)
	at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:969)
	at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1114)
	at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
	at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:64)
	... 24 more
Caused by: java.sql.BatchUpdateException: ORA-01400: Einfügen von NULL in ("ABCD"."TEILNAHME"."NUTZER_ID") nicht möglich

	at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:629)
	at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:9409)
	at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:211)
	at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
	... 32 more
```

Für die Persistenz nutze ich folgende klasse (em und transactionManager werden von Spring injiziert):

```
public class NutzerRepositoryImpl implements NutzerRepositoryI {

	@PersistenceContext
	private EntityManager em;
	
    @Resource
    private PlatformTransactionManager transactionManager;
	
	public NutzerRepositoryImpl(){}
	
	public void addNutzer(Nutzer n) {
		
		em.persist(n);
		em.flush();
		
	}
```

Der Test schaut folgendermaßen aus (nr von Spring injiziert):

```
@Resource(name="nutzerRepo") 
	NutzerRepositoryImpl nr;


	@Test
	public void testU00()
	{
        TransactionStatus transaction = this.transactionManager.getTransaction(new DefaultTransactionDefinition());
		
       
		Nutzer x = new Nutzer();
                ...
		x.setDieTeilnahmen(new ArrayList<Teilnahme>());
		
		Teilnahme t = new Teilnahme();

	        t.setNutzer(x);
		x.getDieTeilnahmen().add(t);
		
		assertNotNull(x);
		assertNotNull(nr);
		assertNotNull(nr.getEm());
		
		nr.addNutzer(x); //<-- hier ist der Knackpunkt
		

		
        transactionManager.commit(transaction);
       
	}
```

Ich hoffe irgendwer kann mir helfen. Ich bin sowieso schon im Verzug mit meiner Projektarbeit...


----------



## Malk (22. Juli 2010)

Ich hab die Beziehungen alle in Unidirektionale geändert. Ist zwar etwas mehr Abfragearbeit, aber besser so, als das mich dieses Problem noch einen weiteren Tag kostet...
Ich hab gelesen, dass dieses Problem wohl Oracle-spezifisch ist.


----------



## minjaman (16. Januar 2011)

Hallo Malk,

Auch wenn es für Deine Projektarbeit zu spät ist ...


```
@JoinColumn(name = "nutzer_id", nullable = false, insertable=false, updatable=false
```

Ohne es auszuprobieren lese ich die Annotation wie folgt: Die Fremdschlüsselspalte soll "nutzer_id" heißen, darf nie mit NULL belegt sein, soll beim insert und beim update ignoriert werden. D.h. sie wird nie von Hibernate befüllt werden. Damit bleibt sie NULL und die Bedingung, dass sie niemals NULL sein darf, ist verletzt.

Mittels SQL-Log lässt sich die Überlegung überprüfen. http://code.google.com/p/jdbcdslog/

Entferne die insertable=false und updateable=false.

Gruß
Alexander


----------

