简体   繁体   中英

Spring boot session.enableFilter cause AssertionFailure: table not found

I'm trying to use spring boot and entitymanager to access mysql db. But if I use session.enableFilter it cause and strange exception. Tried lots of search on the internet but none of them helped.

DataSourceContext.java

@Configuration
@EnableTransactionManagement
public class DataSourceContext {
    public final static String DB_PREFIX = "P_";

    @Autowired
    Environment env;

    @Bean
    @Qualifier("dataSource")
    public DataSource dataSource(Properties hibernateProperties) {
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setUsername(env.getProperty("jdbc.username"));
        ds.setPassword(env.getProperty("jdbc.password"));
        ds.setUrl(env.getProperty("jdbc.url"));
        ds.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        ds.setConnectionProperties(hibernateProperties);
        return ds;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("dataSource") DataSource dataSource, Properties hibernateProperties) {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(true);

        final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setPackagesToScan("com.example.model");
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(hibernateProperties);
        em.setPersistenceUnitName("persistanceUnit");
        em.setPersistenceProviderClass(HibernatePersistenceProvider.class);
        em.afterPropertiesSet();

        return em;
    }

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

    @Bean
    public Properties hibernateProperties() {
        final Properties properties = new Properties();

        properties.put("hibernate.dialect", env.getProperty("hibernate.dialect"));
        properties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql"));
        properties.put("hibernate.format_sql", env.getProperty("hibernate.format_sql"));
        properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
        properties.put("hibernate.default_schema", env.getProperty("hibernate.default_schema"));

        return properties;
    }
}

Aentity.java

@Entity
@Table(name = DataSourceContext.DB_PREFIX + "AENTITY")
@FilterDef(name = "statusFilter", defaultCondition = "STATUS = :status ", parameters = @ParamDef(name = "status", type = "string"))
@Filters({@Filter(name = "statusFilter", condition = "STATUS = :status")})
public class Aentity implements Serializable {
    private Long id;
    private EntityStatus status;
    private Date createdDate;
    private Date updatedDate;
    private Date deletedDate;
    private Long version;

    // getters and setter with column annotations.
}

Adao.java

@Transactional(rollbackFor = Exception.class)
@Repository
public class Adao {

    @PersistenceContext
    protected EntityManager em;

    public EntityManager getEm() {
        /* exception lines */
        em.unwrap(Session.class)
            .enableFilter("statusFilter")
            .setParameter("status", EntityStatus.ACTIVE.name());

        return em;
    }

    public List<Aentity> findAll() {
        List resultList = getEm().createQuery("select distinct aentity from Aentity aentity")
                .getResultList();

        return resultList;
    }
}

pom.xml

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

logs;

----unrelated logs----
2017-04-26 13:32:36.145  INFO 60417 --- [           main] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
2017-04-26 13:32:36.187 ERROR 60417 --- [           main] org.hibernate.AssertionFailure           : HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: Table myschema.P_AENTITY not found
----unrelated logs----

----some logs----
Caused by: org.hibernate.AssertionFailure: Table myschema.P_AENTITY not found
    at org.hibernate.persister.entity.AbstractEntityPersister.getTableId(AbstractEntityPersister.java:5181) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.DynamicFilterAliasGenerator.getAlias(DynamicFilterAliasGenerator.java:31) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.FilterHelper.render(FilterHelper.java:109) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.FilterHelper.render(FilterHelper.java:96) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.filterFragment(AbstractEntityPersister.java:3587) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.internal.JoinSequence.toJoinFragment(JoinSequence.java:175) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.util.JoinProcessor.addJoinNodes(JoinProcessor.java:147) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.util.JoinProcessor.processJoins(JoinProcessor.java:141) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:694) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:673) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:309) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:257) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:262) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:190) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:76) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:150) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:302) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:240) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1894) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:291) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_121]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_121]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298) ~[spring-orm-4.3.8.RELEASE.jar:4.3.8.RELEASE]
    at com.sun.proxy.$Proxy80.createQuery(Unknown Source) ~[na:na]
    at com.example.dao.Adao.findAll(Adao.java:27) ~[classes/:na]
    at com.example.dao.Adao$$FastClassBySpringCGLIB$$c40f7d5e.invoke(<generated>) ~[classes/:na]
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.8.RELEASE.jar:4.3.8.RELEASE]
----some logs----

If I remove enabling filter in Adao.java class then it works fine.

Another case is if I use SessionFactory instead of entitymanager, the result is the same.

How can I solve this problem?

Basically, there is an issue with DynamicFilterAliasGenerator which does not respect the hibernate.default_schema (it knows that there is table P_AENTITY but as it has no information on default scheme it fails to compare the runtime table name myschema.P_AENTITY with the one which it has).

So if you need a quick fix just remove the hibernate.default_schema from you hibernate configuration and relay on jdbc.url . So instead of having something like this

properties.put("hibernate.default_schema", "myschema");

have the schema in JDBC URL like this

DriverManagerDataSource ds = new DriverManagerDataSource();
....
ds.setUrl("jdbc:mysql://localhost:3306/myschema");
....

Firs of all can you check does your hibernate configuration has these properties:

hibernate.dialect=org.hibernate.dialect.MySQLDialect  //you should use mysql dialect from pom I see that you use mysql
#hibernate.default_schema=myCustomName                //commented out in case you want use default schema, else you can use this property to create your custom schema
hibernate.show_sql=true                               //this will help so see what queries are executed
hibernate.format_sql=true                             //this will print formatted sql
hibernate.hbm2ddl.auto=create                         //this will generate database tables if they don't exist in DB, also you can change to "update" this property then database will get updates.

Second thing I suspect that there could be an issue with quotes, they are in JPA style but no in hibernate try (is there reason to have STATUS as upper case in filter? ):

@Entity
@Table(name = DataSourceContext.DB_PREFIX + "AENTITY")
@FilterDef(name = "statusFilter", defaultCondition = "`status` = :status ", parameters = @ParamDef(name = "status", type = "string"))
@Filter(name = "statusFilter", condition = "`status` = :status")
public class Aentity implements Serializable {
    private Long id;
    private EntityStatus status;
    private Date createdDate;
    private Date updatedDate;
    private Date deletedDate;
    private Long version;

    // getters and setter with column annotations.
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM