gpt4 book ai didi

java - 为什么在缺少 @Transactional 时没有抛出 TransactionRequiredException?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:24:10 28 4
gpt4 key购买 nike

我有一个以 Hibernate 作为持久性提供者的 Spring/JPA 配置。但是我不明白为什么当我在没有打开事务的情况下对以下 DAO 代码调用 save() 时没有抛出 TransactionRequiredException(DAO/服务中没有@Transactional):

@Repository
public class UserDao {

@PersistenceContext
private EntityManager entityManager;

public void save(User user) {
entityManager.persist(user);
}
}

正如预期的那样,实体没有保存,但为什么没有抛出异常? javadoc for persist表示 persist() 应该抛出“TransactionRequiredException - 如果在 PersistenceContextType.TRANSACTION 类型的容器管理实体管理器上调用时没有事务”。

调试显示 Hibernate 有一个打开的 session 。这是预期的行为吗?顺便说一句:我在使用 EclipseLink 时得到了相同的行为。

这是我的 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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<context:component-scan base-package="com.foo.bar" />
<context:annotation-config />
<tx:annotation-driven />

<!-- Configure jdbc.properties -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/jdbc.properties" />

<!-- Data Source configuration -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.databaseurl}" p:username="${jdbc.username}" p:password="${jdbc.password}" />

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="HSQL" />
<property name="showSql" value="true" />
</bean>
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

编辑Hibernate 版本(来自 pom.xml)

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.5.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.5.Final</version>
<exclusions>
<exclusion>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
</exclusion>
<exclusion>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>

最佳答案

答案非常简洁明了(实际上是您自己发现的):JPA 需要正在进行的事务才能调用 EntityManager.persist(...)。但是,您的代码未设置为在事务内运行。您的配置看起来很正常,但您在 DAO 或上面的任何层上都缺少 @Transactional

由于最初的问题是为什么不抛出异常,我再次查找规范并发现在 7.9.1 中它明确要求容器在容器管理的持久性上下文中抛出该异常。在 Spring 中运行 JPA 有点介于两者之间,因为我们显然不需要 JTA 等,但可以理解的是,通过注入(inject) EntityManager 您假设处于托管环境中。我提交了 SPR-11923在我们的 JPA 基础设施支持中改进这一点。

旁白:在使用 Spring 和 JPA 时,您可能想看看 Spring Data JPA project ,这显着简化了构建数据访问层的过程,包括存储库层上事务处理的合理默认值(例如,参见 guide)。使用它可以防止您在一开始就遇到这种情况。

关于java - 为什么在缺少 @Transactional 时没有抛出 TransactionRequiredException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24411401/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com