簡體   English   中英

將MariaDB與Hibernate Filter結合使用時,如何獲取AssertionFailure'找不到表'的根本原因?

[英]How to get root cause of AssertionFailure 'Table not found' when using MariaDB with Hibernate Filter?

我正在使用以下測試設置來評估具有各種數據庫的Hibernate Filter功能

  • Spring Boot Starter 1.5.3。發布
  • 休眠5.2.10.Final
  • Spring Data Envers 1.1.3.RELEASE-> Spring Data JPA 1.11.3.RELEASE
  • mariadb-java-client 1.5.9
  • HikariCP 2.6.1
  • MariaDB 10.1.22(docker容器)

數據庫架構是使用Flyway設置的,並且可以正常工作,因此該表就在那里。

現在,我有了一個帶有自定義表名稱和活動字段過濾器的實體類“ User”

@Entity
@Table(name = "\"users\"")
@FilterDef(name = "activeUsers", parameters = @ParamDef(name = "active", type = "boolean"))
@Filter(name = "activeUsers", condition = "\"active\" = :active")
public class User {

    @Id
    private Long id;

    private boolean active;

    // getters/setters (not shown)

}

另外,提供了一個自定義存儲庫以允許使用過濾器:

public interface RepositoryExtended<T> {
     Iterable<T> findAll(boolean active);
}

public class UserRepositoryImpl implements RepositoryExtended<User> {
    @Autowired
    private UserRepository userRepository;

    @Override
    public Iterable<User> findAll(boolean active) {

        EntityManagerHolder holder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(entityManagerFactory);
        EntityManager entityManager = holder.getEntityManager();
        Filter hibernateFilter = entityManager.unwrap(Session.class).enableFilter("activeUsers").setParameter("active", active);
        hibernateFilter.validate();

        Iterable<User> users = userRepository.findAll();
        entityManager.unwrap(Session.class).disableFilter("activeUsers");
        return users;
    }
}

根據上面的Spring Data JPA CrudRepository和自定義存儲庫 ,最終完成UserRepository

public interface UserRepository extends CrudRepository<User, Long>, RepositoryExtended<User> {
}

現在測試設置

@RunWith(SpringRunner.class)
@Transactional
@Rollback
@ContextConfiguration(classes = { DBConfig.class })
public class UserRepositoryTests {

    @PersistenceContext
    private EntityManager em;
    @Autowired
    UserRepository repository;

    @Before
    public void setUp() {
        user = new User();
        user.setActive(true);
        user = repository.save(user);

        user2 = new User();
        user2.setActive(true);
        user2 = repository.save(user2);

        em.flush();
       em.clear();
    }

@Test
    public void filteredQueries() {

        assertEquals(2, repository.count());
        assertTrue(repository.findAll().iterator().hasNext());

        Iterable<User> findAllActive = repository.findAll(true); // THIS FAILS
        assertTrue(findAllActive.iterator().hasNext());
    }
}

使用JDBC和Hibernate / JPA設置

mariadb.db.driver=org.mariadb.jdbc.Driver
mariadb.db.url=jdbc:mariadb://127.0.0.1:3306/PRORK
mariadb.db.username=root
mariadb.db.password=root

hibernate.dialect=org.hibernate.dialect.MariaDB53Dialect
hibernate.globally_quoted_identifiers=true
hibernate.hbm2ddl.auto=validate
hibernate.format_sql=true
hibernate.show_sql=true
hibernate.default_schema=PRORK

在bean配置中使用:

@Configuration
@EnableTransactionManagement
public class DBConfig {

@Bean(destroyMethod = "close")
public DataSource dataSource(Environment env) {
    HikariConfig dataSourceConfig = new HikariConfig();
    dataSourceConfig.setDriverClassName("org.mariadb.jdbc.Driver");
    dataSourceConfig.setJdbcUrl("jdbc:mariadb://127.0.0.1:3306/PRORK");
    dataSourceConfig.setUsername("root");
    dataSourceConfig.setPassword("root");
    return new HikariDataSource(dataSourceConfig);
}

@Bean
public Properties jpaProperties() {
    Properties jpaProperties = new Properties();
    jpaProperties.put(hibernate.dialect, "org.hibernate.dialect.MariaDB53Dialect");
    jpaProperties.put(hibernate.hbm2ddl.auto,"validate");
    jpaProperties.put(hibernate.show_sql,"true");
    jpaProperties.put(hibernate.format_sql,"true");
    jpaProperties.put(hibernate.globally_quoted_identifiers,"true");
    jpaProperties.put(hibernate.default_schema, "PRORK");
    return jpaProperties;
}

@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
    LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactoryBean.setDataSource(dataSource);
    entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    entityManagerFactoryBean.setPackagesToScan("test.prork");
    entityManagerFactoryBean.setJpaProperties(jpaProperties());
    return entityManagerFactoryBean;
}

@Bean
JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    return transactionManager;
}

}

在以下堆棧跟蹤中運行測試結果:

org.hibernate.AssertionFailure: Table `PRORK`.`users` not found
    at org.hibernate.persister.entity.AbstractEntityPersister.getTableId(AbstractEntityPersister.java:5231)
    at org.hibernate.internal.DynamicFilterAliasGenerator.getAlias(DynamicFilterAliasGenerator.java:31)
    at org.hibernate.internal.FilterHelper.render(FilterHelper.java:109)
    at org.hibernate.internal.FilterHelper.render(FilterHelper.java:96)
    at org.hibernate.persister.entity.AbstractEntityPersister.filterFragment(AbstractEntityPersister.java:3641)
    at org.hibernate.engine.internal.JoinSequence.toJoinFragment(JoinSequence.java:201)
    at org.hibernate.engine.internal.JoinSequence.toJoinFragment(JoinSequence.java:187)
    at org.hibernate.hql.internal.ast.util.JoinProcessor.addJoinNodes(JoinProcessor.java:164)
    at org.hibernate.hql.internal.ast.util.JoinProcessor.processJoins(JoinProcessor.java:158)
    at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:785)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:677)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:313)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:261)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:266)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:141)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
    at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:546)
    at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:655)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3318)
    at org.hibernate.query.criteria.internal.CriteriaQueryImpl$1.buildCompiledQuery(CriteriaQueryImpl.java:318)
    at org.hibernate.query.criteria.internal.compile.CriteriaCompiler.compile(CriteriaCompiler.java:127)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:3611)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:203)
    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.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298)
    at com.sun.proxy.$Proxy116.createQuery(Unknown Source)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:656)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.getQuery(SimpleJpaRepository.java:633)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:329)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll(SimpleJpaRepository.java:74)
    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.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:504)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:489)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy120.findAll(Unknown Source)
    at test.prork.persistence.UserRepositoryImpl.findAll(UserRepositoryImpl.java:77)
    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.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:504)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:479)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    at com.sun.proxy.$Proxy120.findAll(Unknown Source)
    at test.prork.persistence.AbstractUserRepositoryTests.filteredQueries(AbstractUserRepositoryTests.java:199)
    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.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
    at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)
    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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:147)
    at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:129)
    at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
    at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
    at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:46)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)

對於H2,PostgreSQL和Oracle DB,相同的測試可以正常工作,只有MariaDB失敗 還要注意,沒有Hibernate過濾器的findAll()方法也可以正常工作,count方法也可以。 未顯示的其他一些基本CrudRepository方法測試對於所有四個數據庫系統也能正常工作。

我在應用過濾器的方法上做錯了什么,而對於其他數據庫系統,它只是偶然地起作用了嗎?

還是對於帶有Hibernate過濾器的MariaDB,要記住任何設置錯誤或特殊設置?

設置/代碼中存在兩個問題

首先, MySQL / MariaDB沒有架構 ,因此刪除

hibernate.default_schema

設置擺脫AssertionFailure,因為它們使用目錄而不是架構。 無論如何,應該由JDBC連接給出。 這張Hibernate JIRA票證給了我必要的提示 ,盡管還有更多票證直接/間接指向此原因。

其次,對於MariaDB,使用過濾器仍然會失敗 (也許對於MySQL來說,也沒有測試)。 這是因為Filter條件中的引號采用JPA樣式,但是目前僅休眠的老式引號 (即使用backtips )似乎可以使用。 完全沒有引號也不起作用。

現在,該實體看起來像:

@Entity
@Table(name = "\"users\"")
@FilterDef(name = "activeUsers", parameters = @ParamDef(name = "active", type = "boolean"))
@Filter(name = "activeUsers", condition = "`active` = :active")
public class User {

    @Id
    private Long id;

    private boolean active;
    // getters/setters (not shown)
}

最后一個技巧幫助我確定了第二個問題: 仔細研究從HQL 生成的Hibernate SQL查詢 ,尤其是有關引號的信息。


更新:我已經在Hibernate JIRA中打開了一張票,因為這可能是Hibernate(MariaDB方言)問題。

這不是錯誤,@ Filter條件值是直接傳遞到數據庫的SQL表達式。

似乎Mariadb支持兩種引號,除非sql_mode =“ ANSI_QUOTES” https://mariadb.com/resources/blog/quotes

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM