2008-12-17 9 views
17

Estoy intentando configurar Spring utilizando Hibernate y JPA, pero cuando intento persistir un objeto, nada parece agregarse a la base de datos.Spring, Hibernate & JPA: La llamada persiste en entitymanager no parece comprometerse con la base de datos

Am utilizando la siguiente:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> 
    <property name="url" value="${jdbc.url}"/> 
    <property name="driverClassName" value="${jdbc.driverClassName}"/> 
    <property name="username" value="${jdbc.username}"/> 
    <property name="password" value="${jdbc.password}"/> 
</bean> 

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="persistenceUnitName" value="BankingWeb" /> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="generateDdl" value="true" /> 
      <property name="showSql" value="true" /> 
      <property name="databasePlatform" value="${hibernate.dialect}" /> 
     </bean> 
    </property> 
</bean> 

<tx:annotation-driven/> 

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory"/> 
</bean> 

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

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/> 

<bean name="accountManager" class="ssel.banking.dao.jpa.AccountManager" /> 
<bean name="userManager" class="ssel.banking.dao.jpa.UserManager" /> 

Y en administrador de cuentas, que estoy haciendo:

@Repository 
public class AccountManager implements IAccountManager { 

    @PersistenceContext private EntityManager em; 

    /* -- 8< -- Query methods omitted -- 8< -- */ 

    public Account storeAccount(Account ac) { 
    ac = em.merge(ac); 
     em.persist(ac); 
     return ac; 
    } 
} 

Dónde ac proviene de:

Account ac = new Account(); 
    ac.setId(mostRecent.getId()+1); 
    ac.setUser(user); 
    ac.setName(accName); 
    ac.setDate(new Date()); 
    ac.setValue(0); 
    ac = accountManager.storeAccount(ac); 
    return ac; 

¿hay alguien que puede apuntar ¿Qué estoy haciendo mal? La llamada persistente regresa sin arrojar excepciones. Si luego hago em.contains(ac), esto devuelve verdadero.

En caso de que alguien necesita, así es como la cuenta se define:

@SuppressWarnings("serial") 
@Entity 
@NamedQueries({ 
     @NamedQuery(name = "Account.AllAccounts", query = "SELECT a FROM Account a"), 
     @NamedQuery(name = "Account.Accounts4User", query = "SELECT a FROM Account a WHERE user=:user"), 
     @NamedQuery(name = "Account.Account4Name", query = "SELECT a FROM Account a WHERE name=:name"), 
     @NamedQuery(name = "Account.MaxId", query = "SELECT MAX(a.id) FROM Account a"), 
     @NamedQuery(name = "Account.Account4Id", query = "SELECT a FROM Account a WHERE id=:id"), 
    }) 
public class Account extends AbstractNamedDomain { 
    @Temporal(TemporalType.DATE) 
    @Column(name = "xdate") 
    private Date date; 

    private double value; 

    @ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE}) 
    @JoinColumn(name="userid") 
    private User user; 

    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    @OneToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE}, fetch=FetchType.EAGER) 
    @OrderBy("date") 
    private List<AccountActivity> accountActivity = new ArrayList<AccountActivity>(); 

    public List<AccountActivity> getAccountActivity() { 
     return accountActivity; 
    } 

    public void setAccountActivity(List<AccountActivity> accountActivity) { 
     this.accountActivity = accountActivity; 
    } 

    public Date getDate() { 
     return date; 
    } 

    public void setDate(Date date) { 
     this.date = date; 
    } 

    public double getValue() { 
     return value; 
    } 

    public void setValue(double value) { 
     this.value = value; 
    } 

    public void addAccountActivity(AccountActivity activity) { 
     // Make sure ordering is maintained, JPA only does this on loading 
     int i = 0; 
     while (i < getAccountActivity().size()) { 
      if (getAccountActivity().get(i).getDate().compareTo(activity.getDate()) <= 0) 
       break; 
      i++; 
     } 
     getAccountActivity().add(i, activity); 
    } 
} 

@MappedSuperclass public abstract class AbstractNamedDomain extends AbstractDomain { 

    private String name; 

    public AbstractNamedDomain() { 

    } 

    public AbstractNamedDomain(String name) { 

     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

@MappedSuperclass public abstract class AbstractDomain implements Serializable { 

    @Id @GeneratedValue 
    private long id = NEW_ID; 

    public static long NEW_ID = -1; 

    public long getId() { 
     return id; 
    } 

    public void setId(long id) { 
     this.id = id; 
    } 

    public boolean isNew() { 

     return id==NEW_ID; 
    } 
} 
+0

hey ruben, estoy haciendo algo similar, pero tengo un archivo persistence.xml, ¿tiene uno, por qué o por qué no? gracias – bmw0128

Respuesta

18

Gracias a Eric y respuestas de Juan Manuel, yo era capaz de darse cuenta de que la transacción no se cometió.

Agregar @Transactional al método storeAccount hizo el truco!

+0

¿Eso es todo lo que hizo para solucionar el problema? –

+0

En mi caso, tuve que agregar @Transactional al punto de entrada de mi clase. Antes solo tenía @Transactional en mi método que hacía persistir. No estoy seguro si entiendo completamente lo que está pasando allí. –

+3

Aparentemente, @Transactional solo funciona en métodos públicos. –

1

Probablemente se esté manteniendo la transacción activa y no está llamando "cometer" hasta que otros métodos que funcionan soporta el extremo transacción activa (todo " votantes" para comprometerse y ninguno de rollback)

Si está seguro de que la entidad que va a persistir está bien que probablemente podría hacer esto:.

@TransactionManagement(TransactionManagementType.BEAN) 
public class AccountManager implements IAccountManager { ..} 

y administrar su persistencia entidad añadiendo:

@Resource 
private SessionContext sessionContext; 

public Account storeAccount(Account ac) { 
    sessionContext.getUserTransaction().begin(); 
    ac = em.merge(ac); 
    em.persist(ac); 
    sessionContext.getUserTransaction().commit(); 
    return ac; 
} 
+0

@TransactionManagement es EJB. –

1

No necesita llamar explícitamente al método persistir. La operación de fusión escribiría los cambios en el DB al confirmar.

4

De hecho, me encontré con otra forma en que esto puede suceder.

En un EntityManager inyectado, no hay actualizaciones cada vez ocurrir si ha especificado persistence.xml así:

<persistence-unit name="primary" transaction-type="RESOURCE_LOCAL">

tiene que quitar el atributo de tipo de transacción y sólo tiene que utilizar el valor por defecto que es JTA .

+1

Después de 6 horas de golpearme la cabeza, encontré esto. – panther

Cuestiones relacionadas