当前位置: 首页 > 知识库问答 >
问题:

在mem数据库中进行测试时,实体管理器未释放锁“无法获取锁”

慕河
2023-03-14

我有一个Spring Boot应用程序,其中包含一些集成测试,用于检查数据库中数据的前端操作结果。

该应用程序在spring-data-jpa和spring-data-rest下方使用DataNcore us JPA,并带有内存数据库,例如Derby,通过Spring Boot测试自动设置。

我以前用Hibernate,但我用它来替换DataNucleus。测试都通过了Hibernate,但现在我的测试JdbcTemplate查询挂起了,好像JPA没有释放它的锁。

我用H2(静默失败)、德比(挂起直到超时)和HSQLDB(永远挂起)尝试过。

我尝试了各种解决方法,例如没有事务(Transactional.TxType.NEVER)或有/没有提交回滚(true/false)

Spring Boot自动实例化数据源,并将其注入EntityManagerFactory和JdbcTemplate。

这是测试:

@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK,
        classes = { TestDataSourceConfig.class })
@EnableAutoConfiguration
@AutoConfigureMockMvc
@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.DERBY)
@Transactional
public class SymbolRestTests  {

    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private SymbolRepository symbolRepository;
    @PersistenceContext
    private EntityManager entityManager;

    @Before
    public void setUp() throws Exception {
        symbolRepository.deleteAll();
        entityManager.flush();
        entityManager.clear();
    }

    @Test
    public void shouldCreateEntity() throws Exception {

        String testTitle = "TEST.CODE.1";
        String testExtra = "Test for SymbolRestTests.java";
        String json = createJsonExample(testTitle, testExtra, true);
        MockHttpServletRequestBuilder requestBuilder =
                post("/symbols").content(json);
        mockMvc.perform(requestBuilder)
                .andExpect(status().isCreated())
                .andExpect(header().string("Location",
                        containsString("symbols/")));
        entityManager.flush();
        entityManager.close(); // this didn't help
        String sql = "SELECT count(*) FROM symbol WHERE title = ?";
        // exception thrown on this next line
        int count = jdbcTemplate.queryForObject(
                sql, new Object[] { testTitle }, Integer.class);
        Assert.assertThat(count, is(1)); 
    }
}

这是来自HSQLDB的错误(似乎信息最丰富):

org.springframework.dao.CannotAcquireLockException: PreparedStatementCallback; 
        SQL [SELECT count(*) FROM symbol WHERE title = ?]; 
        A lock could not be obtained within the time requested;  
        nested exception is java.sql.SQLTransactionRollbackException: 
        A lock could not be obtained within the time requested
    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:259)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:649)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:684)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:716)
    at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:726)
    at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:794)
    at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:813)
    at com.gis.integration.SymbolRestTests.shouldCreateEntity(SymbolRestTests.java:127)
    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.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:316)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:114)
    at org.junit.jupiter.engine.descriptor.MethodTestDescriptor.lambda$invokeTestMethod$6(MethodTestDescriptor.java:171)
    at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40)
    at org.junit.jupiter.engine.descriptor.MethodTestDescriptor.invokeTestMethod(MethodTestDescriptor.java:168)
    at org.junit.jupiter.engine.descriptor.MethodTestDescriptor.execute(MethodTestDescriptor.java:115)
    at org.junit.jupiter.engine.descriptor.MethodTestDescriptor.execute(MethodTestDescriptor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute$1(HierarchicalTestExecutor.java:81)
    at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:76)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute$1(HierarchicalTestExecutor.java:91)
    at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:76)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.lambda$execute$1(HierarchicalTestExecutor.java:91)
    at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:76)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:51)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:87)
    at org.junit.platform.launcher.Launcher.execute(Launcher.java:93)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:61)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.sql.SQLTransactionRollbackException: A lock could not be obtained within the time requested
    at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.wrapInSQLException(Unknown Source)
    at org.apache.derby.impl.jdbc.TransactionResourceImpl.handleException(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedConnection.handleException(Unknown Source)
    at org.apache.derby.impl.jdbc.ConnectionChild.handleException(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedResultSet.closeOnTransactionError(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedResultSet.movePosition(Unknown Source)
    at org.apache.derby.impl.jdbc.EmbedResultSet.next(Unknown Source)
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:92)
    at org.springframework.jdbc.core.RowMapperResultSetExtractor.extractData(RowMapperResultSetExtractor.java:60)
    at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:697)
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:633)
    ... 35 more
Caused by: ERROR 40XL1: A lock could not be obtained within the time requested
    at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
    at org.apache.derby.iapi.error.StandardException.newException(Unknown Source)
    at org.apache.derby.impl.services.locks.ConcurrentLockSet.lockObject(Unknown Source)
    at org.apache.derby.impl.services.locks.ConcurrentLockSet.zeroDurationLockObject(Unknown Source)
    at org.apache.derby.impl.services.locks.AbstractPool.zeroDurationlockObject(Unknown Source)
    at org.apache.derby.impl.services.locks.ConcurrentPool.zeroDurationlockObject(Unknown Source)
    at org.apache.derby.impl.store.raw.xact.RowLocking2nohold.lockRecordForRead(Unknown Source)
    at org.apache.derby.impl.store.access.heap.HeapController.lockRow(Unknown Source)
    at org.apache.derby.impl.store.access.heap.HeapController.lockRow(Unknown Source)
    at org.apache.derby.impl.store.access.btree.index.B2IRowLocking3.lockRowOnPage(Unknown Source)
    at org.apache.derby.impl.store.access.btree.index.B2IRowLocking3._lockScanRow(Unknown Source)
    at org.apache.derby.impl.store.access.btree.index.B2IRowLockingRR.lockScanRow(Unknown Source)
    at org.apache.derby.impl.store.access.btree.BTreeForwardScan.fetchRows(Unknown Source)
    at org.apache.derby.impl.store.access.btree.BTreeScan.fetchNextGroup(Unknown Source)
    at org.apache.derby.impl.sql.execute.BulkTableScanResultSet.reloadArray(Unknown Source)
    at org.apache.derby.impl.sql.execute.BulkTableScanResultSet.getNextRowCore(Unknown Source)
    at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(Unknown Source)
    at org.apache.derby.impl.sql.execute.ScalarAggregateResultSet.getRowFromResultSet(Unknown Source)
    at org.apache.derby.impl.sql.execute.ScalarAggregateResultSet.getNextRowCore(Unknown Source)
    at org.apache.derby.impl.sql.execute.ProjectRestrictResultSet.getNextRowCore(Unknown Source)
    at org.apache.derby.impl.sql.execute.BasicNoPutResultSetImpl.getNextRow(Unknown Source)
    ... 41 more

使用DataNucleus事务文档更新我向持久性添加了一些DataNucleus特定的属性。xml(无结果):

<?xml version="1.0" encoding="UTF-8" ?>
<persistence version="2.1"
        xmlns="http://xmlns.jcp.org/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
            persistence_2_1.xsd">
    <persistence-unit name="test">
        <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>
            <property name="datanucleus.schema.autoCreateAll" value="true"/>
            <property name="datanucleus.transactionIsolation" value="read-uncommitted"/>
            <property name="datanucleus.NontransactionalRead" value="true"/>
            <property name="datanucleus.NontransactionalWrite" value="true"/>
        </properties>
    </persistence-unit>
</persistence>

在调试级别更新#2日志输出,显示DataNucleus JPA/JdbcTemplate日志语句(首先是JPA插入,然后是JdbcTemplate SELECT COUNT(*)):

2017-06-09 14:56:18.055 DEBUG 9492 --- [           main] DataNucleus.Connection                   : ManagedConnection(non-enlisted) "org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl@5621a671 [conn=org.apache.derby.impl.jdbc.EmbedConnection@2006fdaa, commitOnRelease=true, closeOnRelease=true, closeOnTxnEnd=true]" is being committed.
2017-06-09 14:56:18.055 DEBUG 9492 --- [           main] DataNucleus.Connection                   : ManagedConnection(non-enlisted) "org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl@5621a671 [conn=org.apache.derby.impl.jdbc.EmbedConnection@2006fdaa, commitOnRelease=true, closeOnRelease=true, closeOnTxnEnd=true]" closed
2017-06-09 14:56:18.068 DEBUG 9492 --- [           main] DataNucleus.Persistence                  : Object "com.bp.gis.tardis.entity.SymbolEntity@59c08cf1" being inserted into table "SYMBOL"
2017-06-09 14:56:18.071 DEBUG 9492 --- [           main] DataNucleus.Connection                   : ManagedConnection(non-enlisted) "org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl@63a7af06 [conn=null, commitOnRelease=false, closeOnRelease=false, closeOnTxnEnd=true]" opened with isolation level "read-uncommitted" and auto-commit=false
2017-06-09 14:56:18.074 DEBUG 9492 --- [           main] DataNucleus.Transaction                  : Running enlist operation on resource: org.datanucleus.store.rdbms.ConnectionFactoryImpl$EmulatedXAResource@3d4b45b, error code TMNOFLAGS and transaction: [DataNucleus Transaction, ID=Xid=   , enlisted resources=[]]
2017-06-09 14:56:18.076 DEBUG 9492 --- [           main] DataNucleus.Connection                   : ManagedConnection(enlisted) "org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl@63a7af06 [conn=org.apache.derby.impl.jdbc.EmbedConnection@19d76106, commitOnRelease=false, closeOnRelease=false, closeOnTxnEnd=true]" starting for transaction "Xid=   " with flags "0"
2017-06-09 14:56:18.078 DEBUG 9492 --- [           main] DataNucleus.Connection                   : ManagedConnection added to the pool : "org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl@63a7af06 [conn=org.apache.derby.impl.jdbc.EmbedConnection@19d76106, commitOnRelease=false, closeOnRelease=false, closeOnTxnEnd=true]" for key="org.datanucleus.ExecutionContextImpl@2c47a053" in factory="ConnectionFactory:tx[org.datanucleus.store.rdbms.ConnectionFactoryImpl@204c5ddf]"
2017-06-09 14:56:18.125 DEBUG 9492 --- [           main] DataNucleus.Datastore                    : Using PreparedStatement "org.datanucleus.store.rdbms.ParamLoggingPreparedStatement@37753b69" for connection "org.apache.derby.impl.jdbc.EmbedConnection@19d76106"
2017-06-09 14:56:18.134 DEBUG 9492 --- [           main] DataNucleus.Datastore.Native             : INSERT INTO SYMBOL (ACTIVE,CREATED,EXTRA,GLOBAL_READ,GLOBAL_WRITE,LAST_MODIFIED,TITLE) VALUES (<'Y'>,<2017-06-09>,<null>,<'N'>,<'N'>,<2017-06-09>,<'TEST.CODE.1'>)
2017-06-09 14:56:18.169 DEBUG 9492 --- [           main] DataNucleus.Datastore.Persist            : Execution Time = 36 ms (number of rows = 1) on PreparedStatement "org.datanucleus.store.rdbms.ParamLoggingPreparedStatement@37753b69"
2017-06-09 14:56:18.172 DEBUG 9492 --- [           main] DataNucleus.Datastore.Persist            : Object "com.bp.gis.tardis.entity.SymbolEntity@59c08cf1" was inserted in the datastore and was given strategy value of "1"
2017-06-09 14:56:18.179 DEBUG 9492 --- [           main] DataNucleus.Cache                        : Object "com.bp.gis.tardis.entity.SymbolEntity@59c08cf1" (id="org.datanucleus.identity.IdentityReference@93fb44") being changed to be referenced by id="com.bp.gis.tardis.entity.SymbolEntity:1" in Level 1 cache
2017-06-09 14:56:18.180 DEBUG 9492 --- [           main] DataNucleus.Cache                        : Object "com.bp.gis.tardis.entity.SymbolEntity@59c08cf1" (id="com.bp.gis.tardis.entity.SymbolEntity:1") added to Level 1 cache (loadedFlags="[YYYYYYYYY]")
2017-06-09 14:56:18.180 DEBUG 9492 --- [           main] DataNucleus.Transaction                  : Object "com.bp.gis.tardis.entity.SymbolEntity@59c08cf1" (id="org.datanucleus.identity.IdentityReference@93fb44") enlisted in transactional cache is now enlisted using id="com.bp.gis.tardis.entity.SymbolEntity:1"
2017-06-09 14:56:18.181 DEBUG 9492 --- [           main] DataNucleus.Persistence                  : Insert of object "com.bp.gis.tardis.entity.SymbolEntity@59c08cf1" is calling insertPostProcessing for field "com.bp.gis.tardis.entity.SymbolEntity.timeSeriesList"
2017-06-09 14:56:18.181 DEBUG 9492 --- [           main] DataNucleus.Datastore                    : Closing PreparedStatement "org.datanucleus.store.rdbms.ParamLoggingPreparedStatement@37753b69"
2017-06-09 14:56:18.181 DEBUG 9492 --- [           main] DataNucleus.Persistence                  : Insert of object "com.bp.gis.tardis.entity.SymbolEntity@59c08cf1" is calling postInsert for field "com.bp.gis.tardis.entity.SymbolEntity.timeSeriesList"
2017-06-09 14:56:18.205 DEBUG 9492 --- [           main] DataNucleus.Persistence                  : Object "com.bp.gis.tardis.entity.SymbolEntity@59c08cf1" field "timeSeriesList" is replaced by a SCO wrapper of type "org.datanucleus.store.types.wrappers.backed.List" [cache-values=true, lazy-loading=true, allow-nulls=true]
2017-06-09 14:56:18.207 DEBUG 9492 --- [           main] DataNucleus.Persistence                  : ExecutionContext.internalFlush() process finished
2017-06-09 14:56:18.218 DEBUG 9492 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2017-06-09 14:56:18.220 DEBUG 9492 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT count(*) FROM symbol WHERE title = ?]
2017-06-09 14:56:18.250 TRACE 9492 --- [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [TEST.CODE.1], value class [java.lang.String], SQL type unknown
2017-06-09 14:57:18.298  INFO 9492 --- [           main] o.s.b.f.xml.XmlBeanDefinitionReader      : Loading XML bean definitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
2017-06-09 14:57:18.390  INFO 9492 --- [           main] o.s.jdbc.support.SQLErrorCodesFactory    : SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase, Hana]

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /symbols
       Parameters = {}
          Headers = {}

Handler:
             Type = org.springframework.data.rest.webmvc.RepositoryEntityController
           Method = public org.springframework.http.ResponseEntity<org.springframework.hateoas.ResourceSupport> org.springframework.data.rest.webmvc.RepositoryEntityController.postCollectionResource(org.springframework.data.rest.webmvc.RootResourceInformation,org.springframework.data.rest.webmvc.PersistentEntityResource,org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler,java.lang.String) throws org.springframework.web.HttpRequestMethodNotSupportedException

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 201
    Error message = null
          Headers = {X-Application-Context=[application:-1], Location=[http://localhost/symbols/0]}
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = http://localhost/symbols/0
          Cookies = []
2017-06-09 14:57:18.424 DEBUG 9492 --- [           main] DataNucleus.Transaction                  : Transaction rolling back for ExecutionContext org.datanucleus.ExecutionContextImpl@2c47a053
2017-06-09 14:57:18.429 DEBUG 9492 --- [           main] DataNucleus.Lifecycle                    : Object "com.bp.gis.tardis.entity.SymbolEntity@59c08cf1" (id="com.bp.gis.tardis.entity.SymbolEntity:1") has a lifecycle change : "P_NEW"->""
2017-06-09 14:57:18.447 DEBUG 9492 --- [           main] DataNucleus.Transaction                  : Object "com.bp.gis.tardis.entity.SymbolEntity@59c08cf1" (id="com.bp.gis.tardis.entity.SymbolEntity:1") was evicted from transactional cache
2017-06-09 14:57:18.448 DEBUG 9492 --- [           main] DataNucleus.Persistence                  : Disconnecting com.bp.gis.tardis.entity.SymbolEntity@59c08cf1 from StateManager[pc=com.bp.gis.tardis.entity.SymbolEntity@59c08cf1, lifecycle=P_NEW]
2017-06-09 14:57:18.451 DEBUG 9492 --- [           main] DataNucleus.Cache                        : Object with id="com.bp.gis.tardis.entity.SymbolEntity:1" being removed from Level 1 cache [current cache size = 1]
2017-06-09 14:57:18.451 DEBUG 9492 --- [           main] DataNucleus.Transaction                  : Rolling back [DataNucleus Transaction, ID=Xid=   , enlisted resources=[org.datanucleus.store.rdbms.ConnectionFactoryImpl$EmulatedXAResource@3d4b45b]]
2017-06-09 14:57:18.452 DEBUG 9492 --- [           main] DataNucleus.Connection                   : ManagedConnection(enlisted) "org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl@63a7af06 [conn=org.apache.derby.impl.jdbc.EmbedConnection@19d76106, commitOnRelease=false, closeOnRelease=false, closeOnTxnEnd=true]" rolling back for transaction "Xid=   "
2017-06-09 14:57:18.461 DEBUG 9492 --- [           main] DataNucleus.Connection                   : ManagedConnection(non-enlisted) "org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl@63a7af06 [conn=org.apache.derby.impl.jdbc.EmbedConnection@19d76106, commitOnRelease=false, closeOnRelease=false, closeOnTxnEnd=true]" closed
2017-06-09 14:57:18.461 DEBUG 9492 --- [           main] DataNucleus.Connection                   : ManagedConnection removed from the pool : "org.datanucleus.store.rdbms.ConnectionFactoryImpl$ManagedConnectionImpl@63a7af06 [conn=org.apache.derby.impl.jdbc.EmbedConnection@19d76106, commitOnRelease=false, closeOnRelease=false, closeOnTxnEnd=true]" for key="org.datanucleus.ExecutionContextImpl@2c47a053" in factory="ConnectionFactory:tx[org.datanucleus.store.rdbms.ConnectionFactoryImpl@204c5ddf]"
2017-06-09 14:57:18.462 DEBUG 9492 --- [           main] DataNucleus.Transaction                  : Transaction rolled back in 38 ms
2017-06-09 14:57:18.462 DEBUG 9492 --- [           main] DataNucleus.Persistence                  : ExecutionContext "org.datanucleus.ExecutionContextImpl@2c47a053" closed
2017-06-09 14:57:18.463  INFO 9492 --- [           main] o.s.t.c.transaction.TransactionContext   : Rolled back transaction for test context [DefaultTestContext@1f6f0fe2 testClass = SymbolRestTests, testInstance = com.bp.gis.tardis.integration.SymbolRestTests@22604c7e, testMethod = shouldCreateEntity@SymbolRestTests, testException = org.springframework.dao.CannotAcquireLockException: PreparedStatementCallback; SQL [SELECT count(*) FROM symbol WHERE title = ?]; A lock could not be obtained within the time requested; nested exception is java.sql.SQLTransactionRollbackException: A lock could not be obtained within the time requested, mergedContextConfiguration = [WebMergedContextConfiguration@3a48c398 testClass = SymbolRestTests, locations = '{}', classes = '{class com.bp.gis.tardis.config.TestDataSourceConfig, class com.bp.gis.tardis.config.TestDataSourceConfig}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{logging.level.DataNucleus=DEBUG, logging.level.com.bp.gis.tardis=TRACE, logging.level.org.springframework.jdbc.core=TRACE, security.basic.enabled=false, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[[ImportsContextCustomizer@1b4ba615 key = [@org.springframework.boot.autoconfigure.AutoConfigurationPackage(), @org.junit.FixMethodOrder(value=NAME_ASCENDING), @org.springframework.context.annotation.Import(value=[class org.springframework.boot.autoconfigure.AutoConfigurationPackages$Registrar]), @org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase(replace=ANY, connection=DERBY), @org.springframework.boot.autoconfigure.EnableAutoConfiguration(exclude=[], excludeName=[]), @org.springframework.test.context.BootstrapWith(value=class org.springframework.boot.test.context.SpringBootTestContextBootstrapper), @org.junit.jupiter.api.extension.ExtendWith(value=[class org.springframework.test.context.junit.jupiter.SpringExtension]), @org.springframework.transaction.annotation.Transactional(propagation=REQUIRED, rollbackForClassName=[], readOnly=false, isolation=DEFAULT, transactionManager=, noRollbackFor=[], noRollbackForClassName=[], value=, timeout=-1, rollbackFor=[]), @org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc(webDriverEnabled=true, print=DEFAULT, webClientEnabled=true, secure=true, addFilters=true, printOnlyOnFailure=true), @org.springframework.boot.autoconfigure.ImportAutoConfiguration(value=[], exclude=[], classes=[]), @org.junit.platform.commons.meta.API(value=Experimental), @org.springframework.context.annotation.Import(value=[class org.springframework.boot.autoconfigure.ImportAutoConfigurationImportSelector]), @org.springframework.boot.test.autoconfigure.properties.PropertyMapping(value=spring.test.mockmvc, skip=NO), @org.springframework.boot.test.context.SpringBootTest(webEnvironment=MOCK, value=[], properties=[logging.level.DataNucleus=DEBUG, logging.level.com.bp.gis.tardis=TRACE, logging.level.org.springframework.jdbc.core=TRACE, security.basic.enabled=false], classes=[class com.bp.gis.tardis.config.TestDataSourceConfig]), @org.springframework.boot.test.autoconfigure.properties.PropertyMapping(value=spring.test.database, skip=NO), @org.springframework.context.annotation.Import(value=[class org.springframework.boot.autoconfigure.EnableAutoConfigurationImportSelector])]], org.springframework.boot.test.context.SpringBootTestContextCustomizer@702657cc, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@6025e1b6, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@e30f6a3a, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@1ff4931d], resourceBasePath = 'src/main/webapp', contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]]].

更新#3

日志显示了DataNcore us的INSERT,遵循了几个看起来都符合实体对象标准的日志语句,然后出现

ExecutionContext.internalFlush()进程完成

听起来像是DataNucleus EntityManager刷新。然后是Spring的JdbcTemplate中的日志语句,它想读取JPA插入的内容,但都出错了。

共有1个答案

邢乐
2023-03-14

Spring实际上完全包装了其测试框架的EntityManager,包装器只是吞下对entityManager.close()的调用,因此调用不会导致事务完成。

Spring还会在调用entityManager.getTransaction()时引发错误。

通常在我对Spring的体验中,与传统Spring方法(例如带有完全集成Hibernate的Spring数据JPA)一起使用的方法不适用于DataNucleus。

感谢收看此SO Q:如何在@Transactional方法中手动强制提交?

我从类声明中取出了@Transactional注释,没有在测试方法上放置任何内容,并使用REQUIRES_NEW调用了一个单独的方法来执行我想要测试的REST到数据库功能。然后在调用后的原始测试方法中,它都被提交并且没有锁定,因此我可以使用Spring的JdbcTemplate来检查结果。

@Test
public void shouldCreateEntity() throws Exception {

    String testTitle = "TEST.CODE.1";
    String testExtra = "Test for SymbolRestTests.java";
    String json = createJsonExample(testTitle, testExtra, true);
    log.debug(String.format("JSON==%s", json));
    doInNewTransaction(json);
    String sql = "SELECT count(*) FROM symbol WHERE title = ?";
    int count = jdbcTemplate.queryForObject(
            sql, new Object[] { testTitle }, Integer.class);
    Assert.assertThat(count, is(1));
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
private void doInNewTransaction(String json) throws Exception {
    MockHttpServletRequestBuilder requestBuilder =
            post("/symbols").content(json);
    mockMvc.perform(requestBuilder)
            .andExpect(status().isCreated())
            .andExpect(header().string("Location",
                    containsString("symbols/")));
}
 类似资料:
  • 主要内容:1 acquireShared共享式获取锁,1.1 tryAcquireShared尝试获取共享锁,1.2 doAcquireShared自旋获取共享锁,2 reaseShared共享式释放锁,3 acquireSharedInterruptibly共享式可中断获取锁,3.1 doAcquireSharedInterruptibly共享式可中断获取锁,4 tryAcquireSharedNanos共享式超时获取锁,,,,,,详细介绍了AQS中的同步状态的共享式获取、释放的原理,以及独占

  • 我正在尝试获取我的用户名,并在应用程序打开时向他/她问好。但我无法根据某个用户的uid获取数据。当我运行应用程序时,祝酒词从未真正出现。 数据库结构 密码

  • 问题内容: 在Spring MVC中使用PropertyEditor时,让它们从数据库中获取实体是否不好?我应该改为创建一个空实体并设置其ID。 例如,实体Employee: 使用以下GenericEntityEditor在下面的PropertyEditor中获取Entity是一个坏主意: 可以绑定在控制器中: 是否更喜欢对EmployeeEditor使用更具体的方法,并使其仅实例化Employe

  • 问题内容: 我在JavaFx fxml应用程序中都使用了数据库中的Persistence单元和Entity类,我已成功将所有表作为实体导入到Model中,问题是当我尝试插入实体时出现异常和错误,这是我的整个代码 这是当我按下按钮时(当handleButtonAction被触发时)我得到的全部错误。 我在已经存在的类似问题中找不到答案,无法确切知道我所缺少的内容,在此先感谢您的帮助。 问题答案: 为

  • 但问题是这将只锁定一行,而我想在计算总行数时锁定整个表(实体)。 请指教。

  • 我目前正在开发一个解决方案,该解决方案目前有32个UnitTests。我一直在和resharper测试跑步者一起工作--它工作得很好。所有测试都在运行,所有测试都显示了正确的测试结果。 但是,在使用Visual Studio测试资源管理器时,测试不会运行。 Test Explorer将显示所有单元测试,但是一旦单击“Run all”,所有测试都将变灰,并且不显示测试运行的结果: 所有测试类都是公共