I’m trying to setup Spring using Hibernate and JPA, but when trying to persist an object, nothing seems to be added to the database.
Am using the following:
<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' />
And in AccountManager, I’m doing:
@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; } }
Where ac comes from:
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;
Is there anyone who can point out what I’m doing wrong? The persist call returns without throwing exceptions. If afterwards I do em.contains(ac), this returns true.
In case anyone needed, here’s how Account is defined:
@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; } }
Thanks to eric and Juan Manuel’s answers, I was able to figure out that the transaction wasn’t committed.
Adding @Transactional to the storeAccount method did the trick!