Вот код:
// Hibernate модель
@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 contact */
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
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;
}
}
// Сервисный уровень
public void deleteContact(String contactRefId) {
contactDao.delete(contactRefId);
}
// Юнит тест
@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>
Когда я запускаю тестовый метод, никакие исключения не генерируются, но строка в БД не удаляется. Изучение объекта Contact в отладчике после его выборки из БД с помощью критерия attribute.uniqueResult () показывает, что был получен полный и правильный объект. Хотя вызов слияния может показаться ненужным, я сделал это, чтобы увидеть, была ли проблема с неправильным сеансом, используемым для удаления.
Таким образом, представляется, что удаление не вызывается в транзакции, хотя конфигурация Spring проста, и я не вижу никаких потенциальных проблем. Больше всего озадачивает то, что этот код DAO работает:
public void addContact(Contact contact) {
try {
getHibernateTemplate().save(contact);
} catch (DataAccessException e) {
log.error(e.getMessage());
throw e;
}
}
У меня нет идей.