# JPA, Spring, löschen einer Entity



## reinsle (26. Nov 2009)

Hy zusammen,

ich bin im Moment leicht am verzweifeln 

Ich bin ja im Moment dabei eine Anwendung von OJB auf JPA / Hibernate zu Portieren. Was klappt sind die Inserts / Updates, was ich aber nicht schaffe sind die Deletes.

Ich bekomme immer diese Exception:


```
Caused by: java.lang.IllegalArgumentException: Removing a detached instance de.on_ergy.sova.sysadm.data.model.Environment#ASDF    
	at org.hibernate.ejb.event.EJB3DeleteEventListener.performDetachedEntityDeletionCheck(EJB3DeleteEventListener.java:45)
	at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:108)
	at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:74)
	at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:794)
	at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:772)
	at org.hibernate.ejb.AbstractEntityManagerImpl.remove(AbstractEntityManagerImpl.java:253)
	at org.springframework.orm.jpa.JpaTemplate$7.doInJpa(JpaTemplate.java:281)
	at org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:183)
	... 62 more
```

Die persistence.xml

[XML]
<?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"
          xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
          http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
	<persistence-unit name="DataSource" transaction-type="RESOURCE_LOCAL">
		<class>...Environment</class>
		<class>...SourceTyp</class>
		<class>...Umwandlungsprocedure</class>
	</persistence-unit>
</persistence>
[/XML]

Die Spring-Config.xml

[XML]
	<!-- Referenz auf die OSGI-Services -->
	<osgi:reference id="DataSource" interface="...IParameterizedDataSource" />

	<!-- EntitiyManager -->	
	<bean id="EntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" lazy-init="true">
		<property name="dataSource" ref="DataSource" />
		<property name="jpaVendorAdapter">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
				<property name="showSql" value="true" />
				<property name="generateDdl" value="false" />
				<property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
			</bean>
		</property>
		<property name="jpaProperties">
			<props>
				<prop key="hibernate.ejb.naming_strategy">...SysadminNamingStrategy</prop>
				<prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory</prop> 
			</props>
		</property>
	</bean> 

	<!-- Transaction Manager -->
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
		<property name="entityManagerFactory" ref="EntityManagerFactory"/>
		<property name="dataSource" ref="DataSource"/>
	</bean>
	<tx:annotation-driven/>

	<!-- Spring JPA support -->
	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

	<context:annotation-config/>

	<!-- Templates -->
	<bean id="JpaTemplate" class="org.springframework.orm.jpa.JpaTemplate" lazy-init="true">
		<property name="entityManagerFactory" ref="EntityManagerFactory" />
	</bean>

	<!-- DAOs -->
	<bean id="EnvironmentDao" class="...EnvironmentDao">
		<property name="jpaTemplate" ref="JpaTemplate" />
	</bean>
[/XML]

Das Entity:


```
@Entity
public class Environment {
	public static final int LEN_ENVIRONMENT = 8;
	public static final int LEN_BEZEICHNUNG = 256;

	@Id
	@Column(updatable = false, insertable = true, nullable = false, length = 8, unique=true)
	private String environment;
	@Column(length = 256, nullable=false, insertable=true, updatable=true)
	private String bezeichnung;

        [+ die Getter und Setter passend dazu]
}
```

Die Methode zum Löschen schaut dann so aus:


```
/**
	 * Loeschen des Objectes
	 * 
	 * @param entity das Object
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public void delete(final T entity) {
		if (LOG.isInfoEnabled()) {
			LOG.info(MessageFormat.format("Löschen des Objectes: {0}", String.valueOf(entity)));
		}
		getJpaTemplate().merge(entity);
		getJpaTemplate().remove(entity);
	}
```

Das merge hab ich mal mit reingepackt, aber das war so nicht vorgesehen.

Hab im Moment keine Idee mehr was da schieflaufen könnte.

- Transaktionssteuerung sollte ja so funktionieren, weil insert / update ja auch klappt
- Detaches Object heisst ja das die Entity nicht mit der Session verbunden ist, aber das sollte mit dem Merge ja auch tun.

Sonst fällt mir akut nix mehr ein, was da ned tun sollte.

Hat mir evtl jemand n Tipp was ich noch machen kann?

Danke euch.


----------



## maki (26. Nov 2009)

Ich nutze nicht das JpATemplate von Spring sondern den JPA EntityMAnager direkt(wie auch in der Doku empfohlen), aber laut Fehlermeldung versuchst du eine sog. Detached Entity zu löschen, merge sollte dir doch eine attached Entity als Rückgabewert zurückliefern, versuch doch mal diese zu löschen.


```
T attachedEntity = getJpaTemplate().merge(entity);
        getJpaTemplate().remove(attachedEntity);
```


----------



## reinsle (26. Nov 2009)

Hy,



maki hat gesagt.:


> Ich nutze nicht das JpATemplate von Spring sondern den JPA EntityMAnager direkt(wie auch in der Doku empfohlen), aber laut Fehlermeldung versuchst du eine sog. Detached Entity zu löschen, merge sollte dir doch eine attached Entity als Rückgabewert zurückliefern, versuch doch mal diese zu löschen.
> 
> 
> ```
> ...



Und sieheda es funktioniert:


```
/**
	 * Loeschen des Objectes
	 * 
	 * @param entity das Object
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	public void delete(final T entity) {
		if (LOG.isInfoEnabled()) {
			LOG.info(MessageFormat.format("Löschen des Objectes: {0}", String.valueOf(entity)));
		}
		getJpaTemplate().execute(new JpaCallback<T>() {
			public T doInJpa(EntityManager em) throws PersistenceException {
				T e = em.merge(entity);
				em.remove(e);
				return null;
			}
		});
	}
```

Danke dir 

Robert


----------

