在openJPA mySQL中删除实体时的OptimisticLockException

时间:2015-08-31 10:36:02

标签: java mysql openjpa

我在OpenJPA 2.4.0

上使用MySQL

我有3个表格 - meetinglocationmeeting_location

meeting_location是一个联接表,其中有一个外键到meeting,另外两个到location - main_location_idsecondary_location_id

我使用以下参数初始化表,然后尝试从meeting表中删除该条目。

    id  loc_name    
------  ------------
     0  location 0  
     1  location 1  
     2  location 2  
     3  location 3  
     4  location 4  
     5  location 5  
     6  location 6  
     7  location 7  
     8  location 8  
     9  location 9  


         id  name       
------  -----------
     1  meeting 1  


             id  meeting_id  main_location_id  secondary_location_id  name    
------  ----------  ----------------  ---------------------  --------
     1           1                 4                      9  (NULL)  
     2           1                 2                      7  (NULL)  
     3           1                 0                      5  (NULL)  
     4           1                 3                      8  (NULL)  
     5           1                 1                      6  (NULL)  

当我试着打电话时

entityManager.remove(meeting)

我得到org.apache.openjpa.persistence.OptimisticLockException

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.test.StackOverflowQuestionTest.MeetingLocation-3, 
com.test.StackOverflowQuestionTest.MeetingLocation-5, 
com.test.StackOverflowQuestionTest.MeetingLocation-1, 
com.test.StackOverflowQuestionTest.MeetingLocation-2, 
com.test.StackOverflowQuestionTest.MeetingLocation-4]

以下是完整的测试列表:

SQL:

  /*Table structure for table `meeting` */
DROP TABLE IF EXISTS `meeting`;
CREATE TABLE `meeting` (
  `id`                          INT(16) NOT NULL,
  `name`                VARCHAR(128),
  PRIMARY KEY (`id`)

)
  ENGINE =INNODB
  DEFAULT CHARSET =utf8;


        /*Table structure for table `location` */
DROP TABLE IF EXISTS `location`;
CREATE TABLE `location` (
  `id`                          INT(16) NOT NULL,
  `loc_name`            VARCHAR(128),
  PRIMARY KEY (`id`)

)
  ENGINE =INNODB
  DEFAULT CHARSET =utf8;

  /*Table structure for table `meeting_location` */
DROP TABLE IF EXISTS `meeting_location`;
CREATE TABLE `meeting_location` (
  `id`                          INT(16) NOT NULL AUTO_INCREMENT,
  `meeting_id`          INT(16) NOT NULL,
  `main_location_id`        INT(16) NOT NULL,
  `secondary_location_id`       INT(16) NULL,
  `name`                VARCHAR(128),

  PRIMARY KEY (`id`),
  CONSTRAINT `meeting_location_ibfk_1` FOREIGN KEY (`meeting_id`) REFERENCES `meeting` (`id`)
ON DELETE  CASCADE
ON UPDATE  CASCADE      
  ,
  CONSTRAINT `meeting_location_ibfk_2` FOREIGN KEY (`main_location_id`) REFERENCES `location` (`id`)
ON DELETE  CASCADE
ON UPDATE  CASCADE        
  ,
  CONSTRAINT `meeting_location_ibfk_3` FOREIGN KEY (`secondary_location_id`) REFERENCES `location` (`id`)
    ON DELETE  CASCADE
ON UPDATE  CASCADE  
)
  ENGINE =INNODB
  DEFAULT CHARSET =utf8;

实体

@Entity
@Table(name="location")
public class Location {
    @Id
    @Column(columnDefinition="INT")
    private int id;

    @Basic
    @Column(name="loc_name", length=128)
    private String locName;

    public Location() {
    }

    public Location(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getLocName() {
        return locName;
    }

    public void setLocName(String locName) {
        this.locName = locName;
    }
}


@Entity
@Table(name="meeting")
public class Meeting {
    @Id
    @Column(columnDefinition="INT")
    private int id;

    @OneToMany(targetEntity=MeetingLocation.class, mappedBy="meeting", cascade=CascadeType.ALL)
    private Set meetingLocations = new HashSet();

    @Basic
    @Column(length=128)
    private String name;


    public Meeting() {
    }

    public Meeting(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Set getMeetingLocations() {
        return meetingLocations;
    }

    public void setMeetingLocations(Set meetingLocations) {
        this.meetingLocations = meetingLocations;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


@Entity
@Table(name="meeting_location")
public class MeetingLocation {

    @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    @JoinColumn(name="main_location_id", columnDefinition="INT", nullable=false)
    private Location mainLocation;

    @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    @JoinColumn(name="secondary_location_id", columnDefinition="INT")
    private Location secondaryLocation;

    @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    @JoinColumn(name="meeting_id", columnDefinition="INT", nullable=false)
    private Meeting meeting;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition="INT")
    private int id;

    @Basic
    @Column(length=128)
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Location getMainLocation() {
        return mainLocation;
    }

    public void setMainLocation(Location mainLocation) {
        this.mainLocation = mainLocation;
    }

    public Location getSecondaryLocation() {
        return secondaryLocation;
    }

    public void setSecondaryLocation(Location secondaryLocation) {
        this.secondaryLocation = secondaryLocation;
    }

    public MeetingLocation() {
    }

    public MeetingLocation(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }


    public Meeting getMeeting() {
        return meeting;
    }

    public void setMeeting(Meeting meeting) {
        this.meeting = meeting;
    }
}

单元测试:

@ManagedBean
public class SOQuestionTest extends BaseTest {

    private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP_CONFIG, SOQuestionTest.class);
    public static final int MEETING_ID = 1;
    public static final String MEETING_1 = "meeting 1";

    @Resource
    protected UserTransaction transaction;

    @Inject
    private EndUnitDao<EntityManager> alertDao;

    @PersistenceContext(name = "euComm-pu")
    private EntityManager entityManager;

    @Test
    public void SOExampleTest() {

        try {
            transaction.begin();

            Meeting meeting = new Meeting();
            meeting.setName(MEETING_1);
            meeting.setId(MEETING_ID);

            int mainLocationsSize = 5;

            List<Location> locations = new ArrayList<Location>();
            for (int i = 0; i < (mainLocationsSize * 2); i++) {
                Location location = new Location();
                location.setLocName("location " + i);
                location.setId(i);
                locations.add(location);
                entityManager.persist(location);
            }

            for (int i = 0; i < mainLocationsSize; i++) {
                MeetingLocation meetingLocation = new MeetingLocation();
                meetingLocation.setMainLocation(locations.get(i));
                meetingLocation.setSecondaryLocation(locations.get(mainLocationsSize + i));
                meetingLocation.setMeeting(meeting);
                meeting.getMeetingLocations().add(meetingLocation);
            }
            entityManager.persist(meeting);

            this.transaction.commit();

            Meeting meeting1 = entityManager.find(Meeting.class, MEETING_ID);
            Assert.assertEquals(MEETING_1, meeting1.getName());

            this.transaction.begin();
            Meeting meeting2 = entityManager.find(Meeting.class, MEETING_ID);
            //Here I get the OptimisticLockException:
            entityManager.remove(meeting2);
            this.transaction.commit();

            Meeting meeting3 = entityManager.find(Meeting.class, MEETING_ID);
            Assert.assertNull(meeting3);
        }
        catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }
}
  • BaseTest是我们用来管理事务,日志记录和其他常见任务的实用程序类。

日志:

5057  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1491251091 SELECT t0.loc_name FROM location t0 WHERE t0.id = ? [params=(int) 0]
5057  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5058  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1280539125 SELECT t0.loc_name FROM location t0 WHERE t0.id = ? [params=(int) 5]
5058  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5058  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 323248196 SELECT t0.loc_name FROM location t0 WHERE t0.id = ? [params=(int) 1]
5059  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [1 ms] spent
5059  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1301992318 SELECT t0.loc_name FROM location t0 WHERE t0.id = ? [params=(int) 6]
5059  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5060  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 2052728503 SELECT t0.loc_name FROM location t0 WHERE t0.id = ? [params=(int) 4]
5060  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5060  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1414992442 SELECT t0.loc_name FROM location t0 WHERE t0.id = ? [params=(int) 9]
5061  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5061  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1812214031 SELECT t0.loc_name FROM location t0 WHERE t0.id = ? [params=(int) 2]
5061  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5062  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 760487425 SELECT t0.loc_name FROM location t0 WHERE t0.id = ? [params=(int) 7]
5062  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5062  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 518757980 SELECT t0.loc_name FROM location t0 WHERE t0.id = ? [params=(int) 3]
5063  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [1 ms] spent
5063  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 779932859 SELECT t0.loc_name FROM location t0 WHERE t0.id = ? [params=(int) 8]
5063  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5064  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 604225989 DELETE FROM location WHERE id = ? [params=(int) 0]
5064  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5065  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1653474307 DELETE FROM location WHERE id = ? [params=(int) 5]
5065  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5065  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 4677559 DELETE FROM meeting_location WHERE id = ? [params=(int) 3]
5065  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5070  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1283267007 DELETE FROM location WHERE id = ? [params=(int) 1]
5073  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [3 ms] spent
5073  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1004931143 DELETE FROM location WHERE id = ? [params=(int) 6]
5077  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [4 ms] spent
5078  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1040066455 DELETE FROM meeting_location WHERE id = ? [params=(int) 5]
5086  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [8 ms] spent
5086  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 885018785 DELETE FROM location WHERE id = ? [params=(int) 4]
5087  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [1 ms] spent
5087  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 851514585 DELETE FROM location WHERE id = ? [params=(int) 9]
5088  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [1 ms] spent
5088  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1158016054 DELETE FROM meeting_location WHERE id = ? [params=(int) 1]
5088  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5088  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 2065936034 DELETE FROM location WHERE id = ? [params=(int) 2]
5089  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [1 ms] spent
5090  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1432547991 DELETE FROM location WHERE id = ? [params=(int) 7]
5092  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [2 ms] spent
5092  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 49365994 DELETE FROM meeting_location WHERE id = ? [params=(int) 2]
5094  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [2 ms] spent
5094  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 429407697 DELETE FROM location WHERE id = ? [params=(int) 3]
5095  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [1 ms] spent
5096  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 2020466851 DELETE FROM location WHERE id = ? [params=(int) 8]
5106  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [10 ms] spent
5107  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 520296852 DELETE FROM meeting_location WHERE id = ? [params=(int) 4]
5107  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5107  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 549803608 DELETE FROM meeting WHERE id = ? [params=(int) 1]
5108  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [1 ms] spent
Aug 31, 2015 12:45:11 PM org.apache.geronimo.transaction.manager.TransactionImpl beforeCompletion
WARNING: Unexpected exception from beforeCompletion; transaction will roll back
<openjpa-2.4.0-nonfinal-1598334-r422266:1599166 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.test.StackOverflowQuestionTest.MeetingLocation-3, com.test.StackOverflowQuestionTest.MeetingLocation-5, com.test.StackOverflowQuestionTest.MeetingLocation-1, com.test.StackOverflowQuestionTest.MeetingLocation-2, com.test.StackOverflowQuestionTest.MeetingLocation-4]
    at org.apache.openjpa.kernel.BrokerImpl.newFlushException(BrokerImpl.java:2359)
    at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2207)
    at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2105)
    at org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2023)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:527)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:512)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforePrepare(TransactionImpl.java:413)
    at org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:262)
    at org.apache.geronimo.transaction.manager.TransactionManagerImpl.commit(TransactionManagerImpl.java:252)
    at org.apache.openejb.core.CoreUserTransaction.commit(CoreUserTransaction.java:67)
    at com.test.shared.commons.BaseTest$Tx.tx(BaseTest.java:121)
    at com.test.StackOverflowQuestionTest.SOQuestionTest.SOExampleTest(SOQuestionTest.java:106)
    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:483)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1198)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1123)
    at org.testng.TestNG.run(TestNG.java:1031)
    at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
    at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:125)
Caused by: <openjpa-2.4.0-nonfinal-1598334-r422266:1599166 nonfatal store error> org.apache.openjpa.persistence.OptimisticLockException: An optimistic lock violation was detected when flushing object instance "com.test.StackOverflowQuestionTest.MeetingLocation-3" to the data store.  This indicates that the object was concurrently modified in another transaction.
FailedObject: com.test.StackOverflowQuestionTest.MeetingLocation-3
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:124)
    at org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushAndUpdate(BatchingPreparedStatementManagerImpl.java:79)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushInternal(PreparedStatementManagerImpl.java:100)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flush(PreparedStatementManagerImpl.java:88)
    at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:550)
    at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:120)
    at org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:59)
    at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:104)
    at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:77)
    at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:732)
    at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)
    ... 36 more
NestedThrowables:
<openjpa-2.4.0-nonfinal-1598334-r422266:1599166 nonfatal store error> org.apache.openjpa.persistence.OptimisticLockException: An optimistic lock violation was detected when flushing object instance "com.test.StackOverflowQuestionTest.MeetingLocation-5" to the data store.  This indicates that the object was concurrently modified in another transaction.
FailedObject: com.test.StackOverflowQuestionTest.MeetingLocation-5
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushAndUpdate(PreparedStatementManagerImpl.java:124)
    at org.apache.openjpa.jdbc.kernel.BatchingPreparedStatementManagerImpl.flushAndUpdate(BatchingPreparedStatementManagerImpl.java:79)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flushInternal(PreparedStatementManagerImpl.java:100)
    at org.apache.openjpa.jdbc.kernel.PreparedStatementManagerImpl.flush(PreparedStatementManagerImpl.java:88)
    at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:550)
    at org.apache.openjpa.jdbc.kernel.ConstraintUpdateManager.flush(ConstraintUpdateManager.java:120)
    at org.apache.openjpa.jdbc.kernel.BatchingConstraintUpdateManager.flush(BatchingConstraintUpdateManager.java:59)
    at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:104)
    at org.apache.openjpa.jdbc.kernel.AbstractUpdateManager.flush(AbstractUpdateManager.java:77)
    at org.apache.openjpa.jdbc.kernel.JDBCStoreManager.flush(JDBCStoreManager.java:732)
    at org.apache.openjpa.kernel.DelegatingStoreManager.flush(DelegatingStoreManager.java:131)
    at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2207)
    at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2105)
    at org.apache.openjpa.kernel.BrokerImpl.beforeCompletion(BrokerImpl.java:2023)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:527)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforeCompletion(TransactionImpl.java:512)
    at org.apache.geronimo.transaction.manager.TransactionImpl.beforePrepare(TransactionImpl.java:413)
    at org.apache.geronimo.transaction.manager.TransactionImpl.commit(TransactionImpl.java:262)
    at org.apache.geronimo.transaction.manager.TransactionManagerImpl.commit(TransactionManagerImpl.java:252)
    at org.apache.openejb.core.CoreUserTransaction.commit(CoreUserTransaction.java:67)
    at com.test.shared.commons.BaseTest$Tx.tx(BaseTest.java:121)
    at com.test.StackOverflowQuestionTest.SOQuestionTest.SOExampleTest(SOQuestionTest.java:106)
    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:483)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.TestRunner.privateRun(TestRunner.java:767)
    at org.testng.TestRunner.run(TestRunner.java:617)
    at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
    at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
    at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
    at org.testng.SuiteRunner.run(SuiteRunner.java:240)
    at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
    at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
    at org.testng.TestNG.runSuitesSequentially(TestNG.java:1198)
    at org.testng.TestNG.runSuitesLocally(TestNG.java:1123)
    at org.testng.TestNG.run(TestNG.java:1031)
    at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
    at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
    at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)
    at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:125)

1 个答案:

答案 0 :(得分:1)

从你的日志:

5064  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 604225989 DELETE FROM location WHERE id = ? [params=(int) 0]
5064  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5065  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 1653474307 DELETE FROM location WHERE id = ? [params=(int) 5]
5065  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> [0 ms] spent
5065  test-pu  TRACE  [main] openjpa.jdbc.SQL - <t 1394557075, conn 1722642791> executing prepstmnt 4677559 DELETE FROM meeting_location WHERE id = ? [params=(int) 3]

根本原因是

cascade=CascadeType.ALL

问题是当你运行

entityManager.remove(meeting2);

您实际上是在尝试删除与之关联的所有位置。 因为meeting2有两个会议位置,所以它应该失败(即使第二个会议地点没有绑定到另一个会议!)。 JPA通过看到你试图删除你没有FETCH的东西来检测到,这就是它抛出(可能是错误定义的)OptimisticLockException的原因。

一种可能的解决方案是使用另一种不使用DELETE的cascadetype。

如果您不想删除位置,请使用cascadetype.PERSIST或DETACH。