Daten werden nicht gespeichert mit Spring + JPA (Hibernate):

Status
Nicht offen für weitere Antworten.

deamon

Bekanntes Mitglied
Hallo,

ich habe eine von Spring verwaltete Anwendung, in der ich die Daten mit JPA (Hibernate) speichern will. Ich habe folgende Schnittstelle definiert:
Code:
@Transactional
public interface IPageRepository
{
  void add(Page page);
}

Und ich habe zwei Klassen, die zusammen diese Schnittstelle umsetzen:
Code:
public abstract class Repository<T>
{
  protected EntityManager em;

  @PersistenceContext
  void setEntityManager(EntityManager em)
  {
    this.em = em;
  }

  public abstract void add(T t);
}


public class PageRepository extends Repository<Page> implements IPageRepository
{
  @Override
  public void add(Page page)
  {
    page.setAuthor("anonymous");
    page.setRevisionDate(new Date());
    em.merge(page);
    em.flush();
  }

}

Der relevante Teil der Spring-Konfiguration:
Code:
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="myDataSource"/>
</bean>

<tx:annotation-driven transaction-manager="txManager"/>

       <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="myDataSource"/>
        <property name="jpaVendorAdapter">
          <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" />
          </bean>
        </property>
       </bean>

       <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

Wenn ich nun in der Anwendung ein Page-Objekt erzeuge und add übergebe, bekomme ich die Meldung:
Code:
javax.persistence.TransactionRequiredException: no transaction is in progress
Wenn ich em.flush() auskommentiere, passiert einfach nichts. Dabei sollte man doch eigentlich auch ohne diesen expliziten Aufruf auskommen oder? In der DB landet in keinem Fall etwas.

Was mache ich falsch? Ich dachte Spring kümmert sich selbst um die Transaktion? Standardmäßig sollte @Transactional auch mit propagation_required konfiguriert sein, so dass eine neue Transaktion gestartet werden müsste?

Was mache ich falsch? Wie kriege ich den Datensatz in die DB?

Gruß
Christian
 
Die Annotation an der konkreten Klasse anzubringen ändert nichts, aber das hätte mich auch gewundert, denn laut Doku soll man die auch an Schnittstellen schreiben können.
 
Zuletzt bearbeitet:
Unter bestimmten Umständen funktioniert es aber nicht mit Interfaces:

You certainly can place the @Transactional annotation on an interface (or an interface method), but this will only work as you would expect it to if you are using interface-based proxies. The fact that annotations are not inherited means that if you are using class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj") then the transaction settings will not be recognised by the proxying/weaving infrastructure and the object will not be wrapped in a transactional proxy (which would be decidedly bad)

The Spring team's recommendation is that you only annotate concrete classes with the @Transactional annotation, as opposed to annotating interfaces.
 
Danke für den Hinweis! Das Problem war mir gar nicht bewusst. Nur leider ist es nicht das Problem und deshalb auch nicht die Lösung in diesem Fall.

Woran könnte es denn noch liegen, dass die Daten nicht in der DB landen?
 
Danke, das war's! Ich hatte einfach den falschen TransactionManager. Nun verwende ich folgende Konfiguration:

Code:
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="dataSource" ref="myDataSource"/>
        <property name="entityManagerFactory" ref="emf"/>
    </bean>
 
Status
Nicht offen für weitere Antworten.

Zurück
Oben