应该由Spring管理的事务尚未启动。
我是Spring的新手,所以很有可能这是一个简单的问题需要解决,但我无法在互联网上找到任何可以指向正确方向的东西。
<?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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.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-3.0.xsd">
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="123" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
</bean>
</property>
</bean>
<bean id="employeeDAO" class="com.lucas.jpalearning.EmployeeDAO" />
<!-- <property name="entityManagerFactory" ref="entityManagerFactory" /> -->
<bean id="employeeDAOFactoryInjector" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetObject" ref="employeeDAO" />
<property name="targetMethod" value="setEntityManagerFactory" />
<property name="arguments">
<list>
<ref bean="entityManagerFactory"/>
</list>
</property>
</bean>
<tx:advice id="txEmployeeDAO" transaction-manager="txManager">
<tx:attributes>
<tx:method name="persist" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="employeePersistOperation" expression="execution(* com.lucas.jpalearning.EmployeeDAO.*(..))"/>
<aop:advisor advice-ref="txEmployeeDAO" pointcut-ref="employeePersistOperation"/>
</aop:config>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://localhost:5432/lucas"/>
<property name="username" value="lucas"/>
<property name="password" value="XXXXX"/>
</bean>
<context:component-scan base-package="com.lucas.jpalearning" />
<tx:annotation-driven transaction-manager="txManager"/>
<!-- similarly, don't forget the PlatformTransactionManager -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
EmployeeDAO.java:
package com.lucas.jpalearning;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
public class EmployeeDAO {
private EntityManagerFactory entityManagerFactory;
private EntityManager entityManager;
public EmployeeDAO() {
}
//setters for EntityManagerFactory - will be injected by Spring
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
this.setEntityManager(this.entityManagerFactory.createEntityManager());
}
private EntityManagerFactory getEntityManagerFactory() {
return entityManagerFactory;
}
private void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
private EntityManager getEntityManager() {
return this.entityManager;
}
public void persist(Employee employee) {
this.getEntityManager().persist(employee);
this.getEntityManager().flush();
}
}
Main.java:
package com.lucas.jpalearning;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App
{
@PersistenceContext
private static EntityManager em;
public static void main( String[] args )
{
System.out.println( "Hello World!" );
//EntityManagerFactory emf = Persistence
// .createEntityManagerFactory("123");
//em = emf.createEntityManager();
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:META-INF/spring/applicationContext.xml");
EmployeeDAO employeeDAO = ctx.getBean("employeeDAO", EmployeeDAO.class);
employeeDAO.persist(new Employee(1, "Ravi", "Raj", "Textile"));
//createEmployee(1, "Ravi", "Raj", "Textile");
//createEmployee(2, "Amit", "Raj", "IT");
//createEmployee(3, "Nitish", "Kumar", "Marketing");
}
}
的pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lucas</groupId>
<artifactId>jpalearning</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>jpalearning</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9-atlassian-1</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4-redhat-2</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>javax.persistence</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.2.0.Final</version>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1208-jdbc42-atlassian-hosted</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>jBoss-releases-repository</id>
<name>JBoss Releases Repository</name>
<url>https://repository.jboss.org/nexus/content/repositories/releases/</url>
</repository>
<repository>
<id>atlassian-3rd-party-repository</id>
<name>Atlassian 3rd-Party Repository</name>
<url>https://maven.atlassian.com/3rdparty/</url>
</repository>
<repository>
<id>redhat-ga-repository</id>
<name>Redhat GA Repository</name>
<url>https://maven.repository.redhat.com/ga/</url>
</repository>
</repositories>
</project>
的persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="123" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<mapping-file>META-INF/jpa/orm.xml</mapping-file>
<class>com.lucas.jpalearning.Employee</class>
<properties>
<!-- Java Database Connection Specific Properties -->
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/lucas" />
<property name="javax.persistence.jdbc.username" value="lucas" />
<property name="javax.persistence.jdbc.password" value="XXXX" />
<!-- Hibernate Specific Properties -->
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.archive.autodetection" value="class" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
</properties>
</persistence-unit>
</persistence>
控制台输出:
Hello World!
Nov 12, 2016 5:56:13 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@306a30c7: startup date [Sat Nov 12 05:56:13 BRST 2016]; root of context hierarchy
Nov 12, 2016 5:56:13 AM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from URL [file:/home/lucas/workspace/jpalearning/target/classes/META-INF/spring/applicationContext.xml]
Nov 12, 2016 5:56:13 AM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2ef5e5e3: defining beans [entityManagerFactory,employeeDAO,employeeDAOFactoryInjector,txEmployeeDAO,org.springframework.aop.config.internalAutoProxyCreator,employeePersistOperation,org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0,dataSource,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,txManager]; root of factory hierarchy
Nov 12, 2016 5:56:14 AM org.springframework.orm.jpa.LocalEntityManagerFactoryBean createNativeEntityManagerFactory
INFO: Building JPA EntityManagerFactory for persistence unit '123'
Nov 12, 2016 5:56:14 AM org.hibernate.annotations.common.Version <clinit>
INFO: HCANN000001: Hibernate Commons Annotations {4.0.1.Final}
Nov 12, 2016 5:56:14 AM org.hibernate.Version logVersion
INFO: HHH000412: Hibernate Core {4.2.0.Final}
Nov 12, 2016 5:56:14 AM org.hibernate.cfg.Environment <clinit>
INFO: HHH000206: hibernate.properties not found
Nov 12, 2016 5:56:14 AM org.hibernate.cfg.Environment buildBytecodeProvider
INFO: HHH000021: Bytecode provider name : javassist
Nov 12, 2016 5:56:14 AM org.hibernate.cfg.Configuration addResource
INFO: HHH000221: Reading mappings from resource: META-INF/jpa/orm.xml
Nov 12, 2016 5:56:14 AM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000402: Using Hibernate built-in connection pool (not for production use!)
Nov 12, 2016 5:56:14 AM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000115: Hibernate connection pool size: 20
Nov 12, 2016 5:56:14 AM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000006: Autocommit mode: true
Nov 12, 2016 5:56:14 AM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000401: using driver [org.postgresql.Driver] at URL [jdbc:postgresql://localhost:5432/lucas]
Nov 12, 2016 5:56:14 AM org.hibernate.service.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
INFO: HHH000046: Connection properties: {password=****, autocommit=true, release_mode=auto}
Nov 12, 2016 5:56:15 AM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.PostgreSQLDialect
Nov 12, 2016 5:56:15 AM org.hibernate.engine.jdbc.internal.LobCreatorBuilder useContextualLobCreation
INFO: HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException
Nov 12, 2016 5:56:15 AM org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
INFO: HHH000268: Transaction strategy: org.hibernate.engine.transaction.internal.jdbc.JdbcTransactionFactory
Nov 12, 2016 5:56:15 AM org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
INFO: HHH000397: Using ASTQueryTranslatorFactory
Nov 12, 2016 5:56:15 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000228: Running hbm2ddl schema update
Nov 12, 2016 5:56:15 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000102: Fetching database metadata
Nov 12, 2016 5:56:15 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000396: Updating schema
Nov 12, 2016 5:56:15 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000261: Table found: public.employee
Nov 12, 2016 5:56:15 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000037: Columns: [firstname, id, dept, lastname]
Nov 12, 2016 5:56:15 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000108: Foreign keys: []
Nov 12, 2016 5:56:15 AM org.hibernate.tool.hbm2ddl.TableMetadata <init>
INFO: HHH000126: Indexes: [employee_pkey]
Nov 12, 2016 5:56:15 AM org.hibernate.tool.hbm2ddl.SchemaUpdate execute
INFO: HHH000232: Schema update complete
Hibernate:
select
nextval ('hibernate_sequence')
Exception in thread "main" javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:993)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
at com.sun.proxy.$Proxy16.flush(Unknown Source)
at com.lucas.jpalearning.EmployeeDAO.persist(EmployeeDAO.java:51)
at com.lucas.jpalearning.EmployeeDAO$$FastClassByCGLIB$$26523180.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:692)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)
at com.lucas.jpalearning.EmployeeDAO$$EnhancerByCGLIB$$93660a78.persist(<generated>)
at com.lucas.jpalearning.App.main(App.java:29)
编辑:
在使用Spring的log4j之后,我注意到Spring正在启动事务,但是显然没有回滚它。
2016-11-15 02:14:09 DEBUG DefaultListableBeanFactory:251 - Returning cached instance of singleton bean 'employeeDAO'
2016-11-15 02:14:09 DEBUG DefaultListableBeanFactory:251 - Returning cached instance of singleton bean 'txManager'
2016-11-15 02:14:09 DEBUG JpaTransactionManager:367 - Creating new transaction with name [com.lucas.jpalearning.EmployeeDAO.persist]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2016-11-15 02:14:09 DEBUG JpaTransactionManager:371 - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@611f8234] for JPA transaction
2016-11-15 02:14:09 DEBUG AbstractTransactionImpl:158 - begin
2016-11-15 02:14:09 DEBUG LogicalConnectionImpl:212 - Obtaining JDBC connection
2016-11-15 02:14:09 DEBUG LogicalConnectionImpl:218 - Obtained JDBC connection
2016-11-15 02:14:09 DEBUG JdbcTransaction:69 - initial autocommit status: true
2016-11-15 02:14:09 DEBUG JdbcTransaction:71 - disabling autocommit
2016-11-15 02:14:09 DEBUG SQL:104 -
select
nextval ('hibernate_sequence')
Hibernate:
select
nextval ('hibernate_sequence')
2016-11-15 02:14:09 DEBUG LogicalConnectionImpl:212 - Obtaining JDBC connection
2016-11-15 02:14:09 DEBUG DriverManagerConnectionProviderImpl:196 - Opening new JDBC connection
2016-11-15 02:14:09 DEBUG DriverManagerConnectionProviderImpl:219 - Created connection to: jdbc:postgresql://localhost:5432/lucas, Isolation Level: 2
2016-11-15 02:14:09 DEBUG LogicalConnectionImpl:218 - Obtained JDBC connection
2016-11-15 02:14:09 DEBUG SequenceGenerator:127 - Sequence identifier generated: BasicHolder[java.lang.Integer[60]]
2016-11-15 02:14:09 DEBUG AbstractSaveEventListener:130 - Generated identifier: 600, using strategy: org.hibernate.id.SequenceHiLoGenerator
2016-11-15 02:14:10 DEBUG JpaTransactionManager:851 - Initiating transaction rollback
2016-11-15 02:14:10 DEBUG JpaTransactionManager:538 - Rolling back JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@611f8234]
2016-11-15 02:14:10 DEBUG AbstractTransactionImpl:203 - rolling back
2016-11-15 02:14:10 DEBUG JdbcTransaction:164 - rolled JDBC Connection
2016-11-15 02:14:10 DEBUG JdbcTransaction:126 - re-enabling autocommit
2016-11-15 02:14:10 DEBUG JpaTransactionManager:600 - Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@611f8234] after transaction
2016-11-15 02:14:10 DEBUG EntityManagerFactoryUtils:435 - Closing JPA EntityManager
2016-11-15 02:14:10 DEBUG LogicalConnectionImpl:232 - Releasing JDBC connection
2016-11-15 02:14:10 DEBUG LogicalConnectionImpl:250 - Released JDBC connection
Exception in thread "main" javax.persistence.TransactionRequiredException: no transaction is in progress
答案 0 :(得分:1)
需要进行一些更改。
applicationContext.xml:使用LocalContainerEntityManagerFactoryBean。我们想要使用数据源的原因(连接池化源)。删除employeeDAOFactoryInjector,因为我们可以通过使用@PersistenceContext注释来自动装配EntityManager,您也不应该手动创建实体管理器。还要将事务管理器类型更改为PlatformTransactionManager(原因:底部的链接)。
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="123" />
<!-- <property name="packagesToScan" value="com.lucas.jpalearning"/> -->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
</bean>
</property>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- Remove this injector -->
<!-- <bean id="employeeDAOFactoryInjector" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> -->
<!-- Also change transaction manager type -->
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
EmployeeDAO类:
public class EmployeeDAO{
@PersistenceContext
private EntityManager entityManager;
//remove setEntityManagerFactory()
}
现在应该可以使用这些更改。
由于您在很少的地方使用注释并启用了事务注释驱动,让我们尝试注释方式。
删除xml中的 tx-advice 和 aop 标记。
将spring注释@Transactional
放在EmployeeDAO.persist()方法上。
@Transactional
public void persist(Employee employee) {
this.getEntityManager().persist(employee);
this.getEntityManager().flush();
}
注释中的默认事务传播类型为required
,如果没有,则会创建事务管理器。
答案 1 :(得分:0)
您的代码存在两个问题:
(1)您的aop:config
expression
在您需要添加xml
的配置EmployeeDAO
中,如下所示:
<aop:config>
<aop:pointcut id="createOperation"
expression="execution(* com.lucas.jpalearning.EmployeeDAO.persist(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation"/>
</aop:config>
(2)您不应在this.getEntityManager().flush();
中手动执行EmployeeDAO
,因为整个目标声明性事务是通过AOP处理事务(打开,写入,提交或回滚)。