Here is the code:
// Hibernate model
@Entity
@Table(name="contact")
public class Contact {
@Id
@GeneratedValue(strategy= GenerationType.AUTO)
@Column(name = "contact_id")
private Long id;
@Column(name="contact_ref_id")
private String contactRefId;
@Column(name="first_name")
private String firstName;
@Column(name="last_name")
private String lastName;
@ManyToOne
@JoinColumn(name="app_user_id")
/** user whose contact list owns this con开发者_开发百科tact */
private AppUser appUser;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
/**
* @return AppUser who owns contact list this contact belongs to
*/
public AppUser getAppUser() {
return appUser;
}
public void setAppUser(AppUser appUser) {
this.appUser=appUser;
}
public String getContactRefId() {
return contactRefId;
}
public void setContactRefId(String contactRefId) {
this.contactRefId=contactRefId;
}
}
// DAO layer
private Criteria createCriteria() {
return getHibernateTemplate().getSessionFactory().getCurrentSession().createCriteria(Contact.class);
}
public void deleteContact(String contactRefId) {
Criteria criteria = createCriteria();
criteria.add(Restrictions.eq("contactRefId", contactRefId));
Contact contact = (Contact)criteria.uniqueResult();
try {
contact = getHibernateTemplate().merge(contact);
getHibernateTemplate().delete(contact);
} catch (DataAccessException e) {
log.error(e.getMessage());
throw e;
}
}
// Service layer
public void deleteContact(String contactRefId) {
contactDao.delete(contactRefId);
}
// Unit test
@Test
public void testDeleteContact() {
contactService.deleteContact("fe43b43a-d77f-45ce-b024-bb6e93264a69");
}
// Spring config
<beans>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan" value="model.hibernate"/>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
hibernate.query.substitutions=true 'Y', false 'N'
hibernate.cache.use_second_level_cache=true
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
</value>
</property>
</bean>
<!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="contactsDao" class="ContactDaoHibernate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* service..*.*(..))" order="0"/>
</aop:config>
<!-- Enable @Transactional support -->
<tx:annotation-driven/>
<!-- Enable @AspectJ support -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
</beans>
When I fire the test method, no exceptions are thrown, but the row in the db is not deleted. Examination of the Contact object in the debugger after it's fetched from the db by criteria.uniqueResult() reveals the complete and correct object was fetched. Although the merge call may appear unneccesary, I did that to see if there was an issue w/ the wrong Session being used for the delete.
It appears therefore that the the delete is not being called in a transaction, although the Spring config is simple and I don't see any potential issues. What is most perplexing is that this DAO code works:
public void addContact(Contact contact) {
try {
getHibernateTemplate().save(contact);
} catch (DataAccessException e) {
log.error(e.getMessage());
throw e;
}
}
I'm out of ideas.
It's highly recommended to implement equals()
and hashCode()
for your object since you seem to use separate sessions for each operation.
See http://docs.jboss.org/hibernate/core/3.3/reference/en/html/persistent-classes.html#persistent-classes-equalshashcode
Update
It appears that your Spring based unit test does not commit transaction. By default Spring test framework will rollback transaction that it started.
精彩评论