Hi,everyone:
最近在做openjpa和spring的集成,单元测试的时候能够正常的保存,也可以正常的使用jpql语句,
但是,一旦使用删除-delete 和更新-update的时候就会出错
不知道是代码的问题还是事务配置,jpa配置的问题代码:
public interface DAO { public void clear(); public <T> void delete(Class<T> entityClass, Object entityid); public <T> void delete(Class<T> entityClass, Object[] entityids); @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
public <T> T find(Class<T> entityClass, Object entityid); public void save(Object entity); public void update(Object entity);
}
public abstract class DaoSupport implements DAO { @PersistenceContext protected EntityManager em;
public void clear() {
}
public <T> void delete(Class<T> entityClass, Object entityid) {
delete(entityClass, new Object[]{entityid});
} public <T> void delete(Class<T> entityClass, Object[] entityids) {
for(Object id : entityids) {
// em.remove(em.getReference(entityClass, entityids));
em.remove(em.getReference(entityClass, id));
}
} public <T> T find(Class<T> entityClass, Object entityid) {
return em.find(entityClass, entityid);
} public void save(Object entity) {
em.persist(entity);
} public void update(Object entity) {
em.merge(entity);
}
}
------------------------------------spring配置文件beans.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 自动扫描机制 -->
<context:component-scan base-package="com.realhotel"/> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="hotel"/>
</bean>
<!-- 配置使用JPA事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean> <!-- Activates @Transactional for DefaultImageDatabase -->
<tx:annotation-driven transaction-manager="transactionManager"/></beans>
---------------------------------------jpa配置文件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_1_0.xsd" version="1.0">
<!-- http://openjpa.apache.org/faq.html --> <persistence-unit name="hotel" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class>com.realhotel.core.Employee</class>
<class>com.realhotel.core.Student</class>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost:3306/openjpa?useUnicode=true&characterEncoding=UTF-8"/>
<property name="openjpa.ConnectionDriverName" value="org.gjt.mm.mysql.Driver"/>
<property name="openjpa.ConnectionUserName" value="root"/>
<property name="openjpa.ConnectionPassword" value="pass"/>
<property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO,SQL=TRACE"/>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(SchemaAction='add')"/>
</persistence-unit>
</persistence>
---------------------------------------------测试代码-------------------------------
private static ApplicationContext cxt;
private static EmployeeManager employeeManager;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
try {
cxt = new ClassPathXmlApplicationContext("beans.xml");
employeeManager = (EmployeeManager)cxt.getBean("employeeManagerImpl");
} catch (RuntimeException e) {
e.printStackTrace();
}
} @Test
public void testSave() {
// 表employee
Employee emp = new Employee();
emp.setUsername("emp_5");
emp.setPassword("emp_p11");
employeeManager.save(emp);
}
@Test // 测试删除
public void testDelete() {
employeeManager.delete(Employee.class, 1);
}
@Test
public void testFind() {
// 表employee
Employee emp = employeeManager.find(Employee.class,3);
System.out.println(emp.getUsername());
} @Test
public void testUpdate() {
Employee emp = employeeManager.find(Employee.class, 3);
emp.setUsername("改名吧");
emp.setPassword("emp_p11");
employeeManager.update(emp);
}----------testDelete()方法 junit出错信息
org.springframework.orm.jpa.JpaOptimisticLockingFailureException: Optimistic locking errors were detected when flushing to the data store. The following objects may have been concurrently modified in another transaction: [com.realhotel.core.Employee@1fa5e5e]; nested exception is <openjpa-2.0.0-r422266:935683 nonfatal store error> org.apache.openjpa.persistence.OptimisticLockException: Optimistic locking errors were detected when flushing to the data store. The following objects may have been concurrently modified in another transaction: [com.realhotel.core.Employee@1fa5e5e]。Caused by: <openjpa-2.0.0-r422266:935683 nonfatal store error> org.apache.openjpa.persistence.OptimisticLockException: Optimistic locking errors were detected when flushing to the data store. The following objects may have been concurrently modified in another transaction: [com.realhotel.core.Employee@1fa5e5e]
。
Caused by: <openjpa-2.0.0-r422266:935683 nonfatal store error> org.apache.openjpa.persistence.OptimisticLockException: An optimistic lock violation was detected when flushing object instance "com.realhotel.core.Employee-2" to the data store. This indicates that the object was concurrently modified in another transaction.
FailedObject: com.realhotel.core.Employee@1fa5e5e
最近在做openjpa和spring的集成,单元测试的时候能够正常的保存,也可以正常的使用jpql语句,
但是,一旦使用删除-delete 和更新-update的时候就会出错
不知道是代码的问题还是事务配置,jpa配置的问题代码:
public interface DAO { public void clear(); public <T> void delete(Class<T> entityClass, Object entityid); public <T> void delete(Class<T> entityClass, Object[] entityids); @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
public <T> T find(Class<T> entityClass, Object entityid); public void save(Object entity); public void update(Object entity);
}
public abstract class DaoSupport implements DAO { @PersistenceContext protected EntityManager em;
public void clear() {
}
public <T> void delete(Class<T> entityClass, Object entityid) {
delete(entityClass, new Object[]{entityid});
} public <T> void delete(Class<T> entityClass, Object[] entityids) {
for(Object id : entityids) {
// em.remove(em.getReference(entityClass, entityids));
em.remove(em.getReference(entityClass, id));
}
} public <T> T find(Class<T> entityClass, Object entityid) {
return em.find(entityClass, entityid);
} public void save(Object entity) {
em.persist(entity);
} public void update(Object entity) {
em.merge(entity);
}
}
------------------------------------spring配置文件beans.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!-- 自动扫描机制 -->
<context:component-scan base-package="com.realhotel"/> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="hotel"/>
</bean>
<!-- 配置使用JPA事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean> <!-- Activates @Transactional for DefaultImageDatabase -->
<tx:annotation-driven transaction-manager="transactionManager"/></beans>
---------------------------------------jpa配置文件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_1_0.xsd" version="1.0">
<!-- http://openjpa.apache.org/faq.html --> <persistence-unit name="hotel" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class>com.realhotel.core.Employee</class>
<class>com.realhotel.core.Student</class>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:mysql://localhost:3306/openjpa?useUnicode=true&characterEncoding=UTF-8"/>
<property name="openjpa.ConnectionDriverName" value="org.gjt.mm.mysql.Driver"/>
<property name="openjpa.ConnectionUserName" value="root"/>
<property name="openjpa.ConnectionPassword" value="pass"/>
<property name="openjpa.Log" value="DefaultLevel=WARN, Tool=INFO,SQL=TRACE"/>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(SchemaAction='add')"/>
</persistence-unit>
</persistence>
---------------------------------------------测试代码-------------------------------
private static ApplicationContext cxt;
private static EmployeeManager employeeManager;
@BeforeClass
public static void setUpBeforeClass() throws Exception {
try {
cxt = new ClassPathXmlApplicationContext("beans.xml");
employeeManager = (EmployeeManager)cxt.getBean("employeeManagerImpl");
} catch (RuntimeException e) {
e.printStackTrace();
}
} @Test
public void testSave() {
// 表employee
Employee emp = new Employee();
emp.setUsername("emp_5");
emp.setPassword("emp_p11");
employeeManager.save(emp);
}
@Test // 测试删除
public void testDelete() {
employeeManager.delete(Employee.class, 1);
}
@Test
public void testFind() {
// 表employee
Employee emp = employeeManager.find(Employee.class,3);
System.out.println(emp.getUsername());
} @Test
public void testUpdate() {
Employee emp = employeeManager.find(Employee.class, 3);
emp.setUsername("改名吧");
emp.setPassword("emp_p11");
employeeManager.update(emp);
}----------testDelete()方法 junit出错信息
org.springframework.orm.jpa.JpaOptimisticLockingFailureException: Optimistic locking errors were detected when flushing to the data store. The following objects may have been concurrently modified in another transaction: [com.realhotel.core.Employee@1fa5e5e]; nested exception is <openjpa-2.0.0-r422266:935683 nonfatal store error> org.apache.openjpa.persistence.OptimisticLockException: Optimistic locking errors were detected when flushing to the data store. The following objects may have been concurrently modified in another transaction: [com.realhotel.core.Employee@1fa5e5e]。Caused by: <openjpa-2.0.0-r422266:935683 nonfatal store error> org.apache.openjpa.persistence.OptimisticLockException: Optimistic locking errors were detected when flushing to the data store. The following objects may have been concurrently modified in another transaction: [com.realhotel.core.Employee@1fa5e5e]
。
Caused by: <openjpa-2.0.0-r422266:935683 nonfatal store error> org.apache.openjpa.persistence.OptimisticLockException: An optimistic lock violation was detected when flushing object instance "com.realhotel.core.Employee-2" to the data store. This indicates that the object was concurrently modified in another transaction.
FailedObject: com.realhotel.core.Employee@1fa5e5e
解决方案 »
- 急,求助。
- Spring 3 使用-处理整个框架全局的异常
- 请问 在非web项目中数据库连接池应该如何配置
- 讨论:把数据访问层做成通用
- 客户自定义产品数据类型的解决方案
- 一个自己开发的框架,希望有人关注
- 求助 struts配置
- 用HIBERNATE遇到 duplicate import的问题
- 高手们进来看看,这个问题很有挑战性
- org.springframework.web.servlet.DispatcherServlet.initServletBean Context initia
- 关于项目工程的编译选择JDK版本问题!!
- 写了个小程序,计算所有的对称日,如20111102日这种类型的,大家帮忙看下怎么改善下好,现在感觉代码太乱了。
表明的这是一个对数据库的只读方法,比如说select * from ...所以不用开启事务
for(Serializable id : entityids){
em.remove(em.getReference(this.entityClass, id));
}
}
代码没什么问题,是否是结合spring的配置有问题。贴个我使用正常的。
beans.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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:component-scan base-package="com.nbchina"/>
<context:property-placeholder location="classpath:jdbc.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<property name="initialSize" value="${initialSize}"/>
<property name="maxActive" value="${maxActive}"/>
<property name="maxIdle" value="${maxIdle}"/>
<property name="minIdle" value="${minIdle}"/>
</bean> <!--Spring和Jpa结合-->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!--Spring和Jpa结合-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>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_1_0.xsd"
version="1.0"> <persistence-unit name="nbchina" transaction-type="RESOURCE_LOCAL"><!--transaction-type事务类型 -->
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.jdbc.fetch_size" value="18"/>
<property name="hibernate.jdbc.batch_size" value="10"/>
<property name="hibernate.max_fetch_depth" value="3"/> </properties>
</persistence-unit>
</persistence>
ps:我这个代码也是从hibernate-jpa实现移植过来的
org.springframework.orm.jpa.JpaOptimisticLockingFailureException: Optimistic locking errors were detected when flushing to the data store. The following objects may have been concurrently modified in another transaction: [com.realhotel.core.Employee@dc1f04]; nested exception is <openjpa-2.0.0-r422266:935683 nonfatal store error> org.apache.openjpa.persistence.OptimisticLockException: Optimistic locking errors were detected when flushing to the data store. The following objects may have been concurrently modified in another transaction: [com.realhotel.core.Employee@dc1f04]
我觉得最主要的问题还是信息中提到的Optimistic locking 也就是乐观锁的问题
Employee emp = employeeManager.find(Employee.class, 3);
不能给据id=3得到emp
你可以重新做测试:要保证id在数据中存在,就不会出现类似的错误