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&amp;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

解决方案 »

  1.   

    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    表明的这是一个对数据库的只读方法,比如说select * from ...所以不用开启事务
      

  2.   

    问题补充:用Hibernate实现jpa的时候以上的工作情况都是正常的,但是一换到openjpa的时候就出错了
      

  3.   

    删除你用如下这句试试。 public void delete(Serializable ... entityids) {
    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>
      

  4.   

    谢谢你的回复,但是改用openjpa的配置之后发现问题依然存在
    ps:我这个代码也是从hibernate-jpa实现移植过来的
      

  5.   

    这是log信息:
    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 也就是乐观锁的问题
      

  6.   

    配置和事务都没有错误,问题出在
    Employee emp = employeeManager.find(Employee.class, 3);
    不能给据id=3得到emp
    你可以重新做测试:要保证id在数据中存在,就不会出现类似的错误