gpt4 book ai didi

java - 使用Hibernate使用的Javassist实体类进行检测

转载 作者:行者123 更新时间:2023-11-29 03:35:53 25 4
gpt4 key购买 nike

我已经开发了一个库,该库在运行时生成给定抽象类中的某些注释的抽象类的特殊化类。
所以我的库有点像:

X x = newInstance(X.class) //X is an abstract class


该库使用Javassist在运行时生成子类,该子类将由 newInstance方法实例化。

据我了解,Hibernate还利用Javassist在运行时实体类中进行检测(如果不是这样,请有人纠正我)。

我的问题是,是否有可能使两个框架协同工作?我的意思是,我可以告诉Hibernate每次它需要实体类(抽象类)的实例时,都应该使用库中的特定工厂方法吗?

我不知道Hibernate是否也通过在实体类的运行时生成子类来工作(例如,假设Hibernate也需要对其进行检测)。如果真是这样,将某些类传递给Hibernate工厂的解决方案将不起作用。
在那种情况下,Hibernate是否对使用抽象实体类提供任何支持?我的意思是,应该有可能使用抽象(或接口?)实体类,并以某种方式告知Hibernate,当需要使用这些抽象实体类之一时,应该使用哪种正确的具体类。

但是另一个麻烦是,在编译时不存在专门用于抽象实体类的具体类。

最佳答案

在前往您的接送人之前:


是的,您是正确的,Hibernate当前使用Javassist(过去使用GCLib,但已弃用)在运行时检测类。
Hibernate会在运行时创建子类,该子类可以为您的持久实体提供代理。


简短答案

可悲的是,我认为您无法将Hibernate配置为使用自己的工厂。有关详细信息,我邀请您阅读详细答案部分。

长答案

据我所知,当前,Hibernate 4.x仅支持Javassist作为其字节码操作提供程序。虽然,它过去允许您在3.x版本中的GClib和Javassist之间切换。回到这些版本中,您可以通过配置称为hibernate.bytecode.provider的休眠全局设置来修改要使用的工厂。

此设置不再显示在Hibernate 4.1 documentation中,但是您仍然可以在optional configuration properties下的Hibernate 3.2文档中找到有关此设置的信息。

作为自己的开发人员,我知道有时候我们会有些棘手,仅仅因为文档中有某些内容并不意味着它就不在代码中了:-)因此,即使设置仍然存在,我也可以尝试利用以便执行您想要的操作(不过以不受支持的方式)。

为求好奇,自从我在计算机中使用了Hibernate 4.0.1代码(尽管不是最新的通知)后,我做了一些挖掘工作...惊奇,惊奇地,该属性仍然存在!跟踪使用的引用(感谢Eclipse)后,我进入了org.hibernate.cfg.Environment(code for version 4.2.0.CR2)类,在其中发现了以下代码(我的版本和4.2.0CR2中的代码相同):

 public static BytecodeProvider buildBytecodeProvider(Properties properties) {
String provider = ConfigurationHelper.getString( BYTECODE_PROVIDER, properties, "javassist" );
LOG.bytecodeProvider( provider );
return buildBytecodeProvider( provider );
}

private static BytecodeProvider buildBytecodeProvider(String providerName) {
if ( "javassist".equals( providerName ) ) {
return new org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl();
}

LOG.unknownBytecodeProvider( providerName );
return new org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl();
}


到目前为止,我可以说它是代理工厂的Javassist实现,并且没有标准的方法可以更改它。



疯子注

我要说的是纯粹的疯狂,在生产代码中不应将其考虑在内,而只有在切实可行的情况下/学术/让事情变本加厉。

<锤击黑客>


您可以尝试扩展自己的框架来检测类,以便不仅添加满足您需求的字节码,还添加休眠所需的字节码-我想这就像将您的操作与 org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl操作合并一样。
然后,您可以将扩展类重命名为 BytecodeProviderImpl,并将其放在相同的包 org.hibernate.bytecode.internal.javassist中,最后将其放在类路径中的某个位置,在该路径中,类加载器会在jar中找到它(或者可以使用自定义类加载器)


然后,您将只喜欢听Hibernate,您的框架以及恐怕不知道该怎么做的整个JVM尖叫,否则它可能会起作用...



无论如何,如果您有时间并且愿意尝试,请告诉我是否可行。



更新

在评论部分稍作讨论后,我有了使用自定义 EntityPersister的想法。由于我对此不太确定,因此我在Google上搜索了一下,是否可以找到可以告诉我我在想的东西行得通的东西。

甚至比发现自己的直觉是否正确还好,我还在Stackoverflow中发现了一个问题,似乎是 pretty similar to yours。可悲的是,那里没有公认的答案。

但是,该问题的第一个答案提供了与我所想的类似的链接。引用Pascal Thivent:


  自定义EntityPersister实现(您可以 register for a particular entity during Hibernate initialization using a custom Configuration


确实,该示例适用于Grails中的Hibernate,但在普通Java中几乎相同:

 public void registerCustomEntityPersister(Configuration configuration) {
final Iterator<PersistentClass> classesIterator = configuration.getClassMappings();
while (classesIterator.hasNext()) {
final PersistentClass persistentClass = classesIterator.next();
if (checkIfIsOneTheClassesThatMatters(persistentClass)) {
persistentClass.etEntityPersisterClass(CustomEntityPersister.class);
}
}


即使这似乎可行,但看起来工作量太大,因为实现EntityPersister看起来并不琐碎……太多的事情。您可以尝试扩展Hibernate使用的默认值(我真的不知道是哪个),并尝试重写getProxy()方法以返回您所检测的类之一。

抱歉,如果仍然不能解决问题,但是很遗憾,我不是Hibernate专家,我通常是开箱即用,由于javassist标签,我实际上落在了您的问题上,并发现它很有趣。

我希望至少我给您提供了可以帮助您的信息。

关于java - 使用Hibernate使用的Javassist实体类进行检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15587061/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com