Estoy tratando de configurar la Primavera usando Hibernate y JPA, pero cuando se trata de persistir un objeto, nada parece ser añadido a la base de datos.

Estoy usando el 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 AccountManager, yo 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;
    }
}

Donde 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 señalar lo que estoy haciendo mal? El persistir de la llamada devuelve sin lanzar excepciones. Si después hago em.contains(ac), este devuelve true.

En caso de que alguien necesite, he aquí cómo 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;
}
}
  • hola ruben, yo estoy haciendo algo similar, pero tengo un persistence.xml archivo, ¿tienes uno, ¿por qué o por qué no? gracias

4 Comentarios

  1. 18

    Gracias a eric y Juan Manuel respuestas, yo era capaz de averiguar de que la transacción no fue cometido.

    La adición de @Transaccional a la storeAccount método hizo el truco!

    • Es que todo lo que hiciste para solucionar el problema?
    • En mi caso he tenido que añadir @Transaccional al punto de entrada de mi clase. Antes de que yo sólo tenía @Transactional mi método que hizo la persistencia. No sé si estoy totalmente de entender lo que está pasando allí.
    • Al parecer @Transactional sólo funciona en los métodos públicos.
    • Gracias, has salvado mi día también!
    • Funciona!…parece que cuando el @Transactional se agrega a un método específico, se especifica automáticamente las etapas de la transacción (begin,commit, rubor, etc)
  2. 4

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

    En la inyección de un EntityManager, no se actualiza nunca va a ocurrir si usted tiene persistence.xml especificados como esto:

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

    Que usted necesita para eliminar la transacción de tipo de atributo y sólo tiene que utilizar el valor por defecto que es JTA.

    • Después de 6 horas de golpear mi cabeza, encontré esto.
  3. 1

    Usted explícitamente, no es necesario llamar a la persistir método. La operación de combinación de escribir los cambios a la base de datos a cometer.

  4. 1

    Probablemente estás manteniendo la transacción activa y no está llamando a un «commit» de hasta otros métodos que ejecuta el apoyo de la transacción activa final (todos los «votantes» para confirmar y ninguno para la reversión.)

    Si está seguro de que la entidad va a persistir es aceptar que probablemente se podría hacer esto:

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

    y administrar su entidad, la persistencia de la adición:

    @Resource
    private SessionContext sessionContext;
    public Account storeAccount(Account ac) {
    sessionContext.getUserTransaction().begin();
    ac = em.merge(ac);
    em.persist(ac);
    sessionContext.getUserTransaction().commit();
    return ac;
    }
    • es EJB.

Dejar respuesta

Please enter your comment!
Please enter your name here