博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
剖析javax.persistence.Table.indexes()异常原因
阅读量:6830 次
发布时间:2019-06-26

本文共 6872 字,大约阅读时间需要 22 分钟。

hot3.png

1.异常内容

我遇到的具体现象是,将工程发布到tomcat可以正常运行,但是通过junit跑测试,就会如下错误:

Caused by: java.lang.NoSuchMethodError: javax.persistence.Table.indexes()[Ljavax/persistence/Index;	at org.hibernate.cfg.annotations.EntityBinder.processComplementaryTableDefinitions(EntityBinder.java:936) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]	at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:824) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]	at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3788) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]	at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3742) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]	at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1410) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]	at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:397) ~[hibernate-core-4.3.5.Final.jar:4.3.5.Final]	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842) ~[hibernate-entitymanager-4.3.5.Final.jar:4.3.5.Final]	at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60) ~[spring-orm-4.1.1.RELEASE.jar:4.1.1.RELEASE]	at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-4.1.1.RELEASE.jar:4.1.1.RELEASE]	at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318) ~[spring-orm-4.1.1.RELEASE.jar:4.1.1.RELEASE]	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1627) ~[spring-beans-4.1.1.RELEASE.jar:4.1.1.RELEASE]	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1564) ~[spring-beans-4.1.1.RELEASE.jar:4.1.1.RELEASE]	... 25 more

如果按照网上的一些解决办法,将@Table(name="t_user")改写为@Entity(name="t_user")这种形式,问题依然无法解决的,会出现如下的Exception:

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: User is not mapped	at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:189)	at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:109)	at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromClause.java:95)	at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:331)	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3633)	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3522)	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:706)	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:562)	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:299)	at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:247)	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278)	at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)	... 42 more

2.原因定位

顺着异常提示信息,打开hibernate-core-4.3.5.Final.jar:4.3.5.Final这个jar包(我用的反编译工具),一路追到这个类org.hibernate.cfg.AnnotationBinder,在bindClass方法中,可以发现在最后面连续调用了三次EntityBinder类的processComplementaryTableDefinitions方法,也就是异常信息中最后抛出Exception的方法。

public static void bindClass(XClass clazzToProcess, Map
inheritanceStatePerClass, Mappings mappings) throws MappingException{ //此处省略N行代码 mappings.addClass(persistentClass); mappings.addSecondPass(new SecondaryTableSecondPass(entityBinder, propertyHolder, clazzToProcess)); entityBinder.processComplementaryTableDefinitions((org.hibernate.annotations.Table)clazzToProcess.getAnnotation(org.hibernate.annotations.Table.class)); entityBinder.processComplementaryTableDefinitions((Tables)clazzToProcess.getAnnotation(Tables.class)); entityBinder.processComplementaryTableDefinitions(tabAnn);}

再打开EntityBinder类,可以发现有两个同名的processComplementaryTableDefinitions方法,两个方法中都调用了table.indexes(),两个方法的参数虽然都是table,但是类型是不同的。一个是JPA api中的Table类,另一个是hibernate的Table类。

public void processComplementaryTableDefinitions(javax.persistence.Table table) {    if (table == null) return;    TableBinder.addIndexes(this.persistentClass.getTable(), table.indexes(), this.mappings);}
public void processComplementaryTableDefinitions(org.hibernate.annotations.Table table) {    if (table == null) return;    String appliedTable = table.appliesTo();    Iterator tables = this.persistentClass.getTableClosureIterator();    org.hibernate.mapping.Table hibTable = null;    while (tables.hasNext()) {      org.hibernate.mapping.Table pcTable = (org.hibernate.mapping.Table)tables.next();      if (pcTable.getQuotedName().equals(appliedTable))      {        hibTable = pcTable;        break;      }      hibTable = null;    }    if (hibTable == null)    {      for (Join join : this.secondaryTables.values()) {        if (join.getTable().getQuotedName().equals(appliedTable)) {          hibTable = join.getTable();          break;        }      }    }    if (hibTable == null) {      throw new AnnotationException("@org.hibernate.annotations.Table references an unknown table: " + appliedTable);    }    if (!BinderHelper.isEmptyAnnotationValue(table.comment())) hibTable.setComment(table.comment());    TableBinder.addIndexes(hibTable, table.indexes(), this.mappings);  }
回头再看看异常信息,指向的是 javax.persistence.Table这个类的indexes方法。首先想到的是打开 hibernate-jpa-2.1-api-1.0.0.Final.jar这个jar包,找到 javax.persistence.Table,一探究竟。结果两个类都是有indexes这个方法的,不免让人挠头,莫非有鬼。

后来仔细一想,javax.persistence.Table是JPA标准api类,不一定就只有那个jar包里有啊,赶紧打开Java Build Path看了一下,发现了EclipseLink这玩意

这厮的jar包里果然有个没有indexes方法的Table类,再仔细看看jar包的名字"javax.persistence_2.0.4",原来这是JPA2.0的,而Table的indexes在JPA2.1中才有的,而junit在运行的时候,恰巧是先走了这个jar包中的类。

3.总结分析

Hibernate在进行注解处理的过程中,既处理了JPA标准的注解,也处理了hibernate特有的注解,hibernate4.3处理注解是基于JPA2.1版本的,所以,我推想,其他遇到这个exception的朋友,很有可能也是使用的jar包中有旧版本的Table类。不妨用JarSearch搜索下,就可以发现问题。

转载于:https://my.oschina.net/JasonZhang/blog/539095

你可能感兴趣的文章
19个非常有用的 jQuery 图片滑动插件和教程
查看>>
Android XML shape 标签使用详解
查看>>
android 成长日记 4.BaseActivity的实现和ActivityCollectio实现
查看>>
linux64位编译php遇到configure: error: GD build test failed. Please check the config.log for details...
查看>>
oracle 启动 命令
查看>>
使用python写糗事百科的爬虫
查看>>
$MFTMirr does not match $MFT (record 0)问题解决
查看>>
oracle 修改列
查看>>
python-03:用最简单快速的方法入门
查看>>
CentOS7网卡绑定
查看>>
LAMP-HTTPD服务器配置
查看>>
linux安装ICMP shell(icmp后门)
查看>>
JSP 上传图片之前先在页面生成预览
查看>>
ICMP协议-路由交换原理4-【HCNA笔记】
查看>>
Performing RMAN Tablespace Point-in-time Recovery(TSPITR)
查看>>
弱引用研究
查看>>
JQuery 判断checkbox是否选中,checkbox全选,获取checkbox选中值
查看>>
高考焦虑现象源于就业焦虑
查看>>
Lync Server 2013企业版部署系列之二:准备DNS
查看>>
启动3个线程轮番打印递增的数字
查看>>