Hibernate对Java 9的支持
Hibernate是否已准备好使用Java 9的可用版本?
我记得我已经尝试过但它失败了。 不幸的是我不记得具体原因。
顺便说一句,Hibernate Validator 5.2.3已经可以与Java 9一起使用了。
我想知道同样的事情,并尝试在Java 9的早期访问版本下运行我的Hibernate应用程序。这是我学到的。
我遇到的第一个问题是javax.xml.bind.JAXBException的ClassNotFoundException。 自Java 6以来,JAXB一直处于运行时类路径中,但在Java 9中,默认情况下不再发布它。 至少有两种方法可以解决这个问题:
- 在Java 9 JVM中运行程序时,请包含命令行参数“–add-modules java.se.ee”。 这指示Java 9再次在类路径中包含JAXB(和其他库)。 但请记住,这个论点将被Java 8 JVM拒绝; 因此,如果您允许用户在多个Java版本下运行,则必须动态计算命令行,或者要求用户手动编辑命令行。
-
在应用程序中包含JAXB库。 如果您的Hibernate应用程序是注释驱动的,它可能实际上并不需要任何JAXB 实现 ,在这种情况下,您只能包含JAXB API。 这是我添加到我的pom的依赖:
javax.xml.bind jaxb-api 2.2.11
解决了JAXB问题后,我运行了应用程序并收到了几千行堆栈跟踪,如下所示:
java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @49f97198 at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:337) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:281) at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:197) at java.base/java.lang.reflect.Method.setAccessible(Method.java:191) at javassist.util.proxy.SecurityActions.setAccessible(SecurityActions.java:103) at javassist.util.proxy.FactoryHelper.toClass2(FactoryHelper.java:181) at javassist.util.proxy.FactoryHelper.toClass(FactoryHelper.java:164) at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:507) at javassist.util.proxy.ProxyFactory.createClass2(ProxyFactory.java:492) at javassist.util.proxy.ProxyFactory.createClass1(ProxyFactory.java:428) at javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:400) at org.hibernate.proxy.pojo.javassist.JavassistProxyFactory.postInstantiate(JavassistProxyFactory.java:72) at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:162) at org.hibernate.tuple.entity.AbstractEntityTuplizer.(AbstractEntityTuplizer.java:163) at org.hibernate.tuple.entity.PojoEntityTuplizer. (PojoEntityTuplizer.java:58)
在这些例外情况之后,您的应用可能会正常运行。 但不要被愚弄:对象的延迟初始化已被禁用。 因此,您可能会遇到严重的性能问题。
发生这些错误是因为Hibernate的运行时字节码增强被新模块系统中的强封装规则阻止。 有关此问题的详细说明,请参阅此stackoverflowpost 。
如该post所述,您可以在启动JVM时通过添加另一个命令行参数来消除这些错误。 但这种方法只是一种解决方法,而不是一个好的长期解决方案。
经过多次试验和错误,我发现了一个更好的解决方案:
- 使用Hibernate 5.0.0或更高版本(早期版本不起作用)和
- 请求构建时字节码增强 (使用Gradle,Maven或Ant插件)。
这避免了Hibernate在运行时执行基于Javassist的类修改的需要,从而消除了上面显示的堆栈跟踪。 我用Hibernate 5.0.12.FINAL,5.1.5.Final和5.2.9.Final测试了这个。
但是 ,您应该在之后彻底测试您的应用程序。 Hibernate在构建时应用的字节码更改似乎与运行时应用的字节码更改不同,导致应用程序行为略有不同。 当我启用构建时字节码增强时,我的应用程序中已经成功多年的unit testing突然失败了。 (我不得不追逐新的LazyInitializationException错误和其他问题。)而且行为似乎从一个版本的Hibernate到另一个版本不等; 我可以修复我的unit testing在5.0.12中工作,只是看到它们在5.1.5中再次失败。 谨慎行事。
- Ignite for Hibernate L2非常慢
- 如何在hibernate中启用批量插入?
- Hibernate 4.1.9(最新的最终版本)报告`不支持嵌套事务`
- 如何在数据库中通过Spring Hibernate在TextBox中插入Gujarati?
- 使用EAGER @ElementCollection对find()进行Hibernate LazyInitializationException
- 带有Hibernate 4和ManyToOne级联的IllegalStateException
- 将数据从一个数据库复制到另一个数据库时如何解决org.hibernate.StaleObjectStateException?
- com.thoughtworks.xstream.converters.ConversionException
- Spring Boot:在Quartz作业执行中使用@Service