在对您的原始问题进行了更多思考之后,我想补充一下:
Spring 不会自动用 Transaction 包装每个方法。你必须告诉 Spring 你希望你的事务边界在哪里。您可以使用 XML 配置或使用 @Transactional 注释来执行此操作。
你应该看看你应该在哪里声明交易——这里和这里。
你应该看看 Spring 的事务管理 -这里。
你应该看看 Transaction Config - here。
我仍然认为您的配置很好,并且您遇到的问题在于尝试使用您的 EntityManager 的 bean。我再次请求你发布它,因为我确信如果我能看到它,我可以让你去。
我查看了您的配置,但没有发现任何问题。作为一个例子,我将(在底部)提供我现在在一个工作应用程序中的一些东西。
我不相信您的问题出在您的配置中,而在于您对已配置 bean 的使用。如果您可以提供向我(我们)展示您如何与 EntityManager 交互的代码,我可能会发现您的问题。
我将为您提供实体、存储库和 XML 配置的工作示例,以尝试帮助您找到问题:
弹簧配置(applicationContext.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:annotation-config />
<context:component-scan base-package="com.company.app.dao" />
<context:component-scan base-package="com.company.app.service" />
<jee:jndi-lookup id="dataSource"
jndi-name="jdbc/Test" />
<bean id="jpaDialect"
class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<bean id="jpaAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
<bean id="entityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
<property name="packagesToScan" value="com.company.app.model" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManager" />
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
</beans>
模型
import org.hibernate.validator.constraints.Length;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@Entity
public class User {
@Id
private String id = UUID.randomUUID().toString();
@Column
@Length(min = 3, max = 25)
private String name;
@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "userId", nullable = false)
private Set<Contact> contacts = new HashSet<Contact>();
public UUID getId() {
return UUID.fromString(id);
}
public void setId(UUID id) {
this.id = id.toString();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Contact> getContacts() {
return contacts;
}
public void setContacts(Set<Contact> contacts) {
this.contacts = contacts;
}
public void addContact(Contact contact) {
this.contacts.add(contact);
}
public void removeContact(Contact contact) {
this.contacts.remove(contact);
}
}
存储库
import com.company.app.model.User;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaQuery;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@Repository
public class UserDao {
@PersistenceContext
private EntityManager em;
@Transactional(propagation = Propagation.REQUIRED)
public void createUser(User user) {
em.persist(user);
}
@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
public User readUserById(UUID id) {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
query.where (em.getCriteriaBuilder().equal(query.from(User.class).get("id"),id.toString()));
return em.createQuery(query).getSingleResult();
}
@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
public Set<User> readAll() {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
query.from(User.class);
return new HashSet<User>(em.createQuery(query).getResultList());
}
@Transactional(propagation = Propagation.REQUIRED)
public User update(User user) {
return em.merge(user);
}
@Transactional(propagation = Propagation.REQUIRED)
public void delete(User user) {
em.remove(user);
}
}