バックグラウンド
Groovyのクラスローダーを使用してクラスとして解析する一連のGroovyファイルがあります。
GroovyClassLoader gcl = new GroovyClassLoader();
while (groovyIter.hasNext()) {
File groovyFile = (File) groovyIter.next();
try {
Class clazz = gcl.parseClass(groovyFile);
} catch (IOException ioe) {
log.error("Unable to read file " + groovyFile + " to parse class ", ioe);
}
}
GroovyClassLoader が完成したら、XStream を使用して XML ファイルを解析し、XML を Groovy オブジェクトの異なるインスタンスとして逆シリアル化します。今のところ、請求書という 1 つのタイプから始めています。XStream が Groovy クラスを認識できるように、クラスローダーを GroovyClassLoader のインスタンスに設定します。
XStream xstream = new XStream();
xstream.setClassLoader(gcl);
// Read the file and get objects
Object deserialized = xstream.fromXML(file);
デシリアライズされたオブジェクトを取得したら、Hibernate を使用してデータベースに格納します。私のhibernate.config.xmlには、マッピングエントリがあります
<mapping class="invoice"/>
注釈付きの groovy クラスに対応するもの
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.persistence.GenerationType
import groovy.transform.ToString
import groovy.transform.EqualsAndHashCode
import javax.persistence.Table
import javax.persistence.Column
@ToString
@EqualsAndHashCode
@Entity
@Table(name="invoice")
class invoice {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long id
String invoicedate
String invoicenumber
String ponumber
String salesrep
String servicedate
String terms
String duedate
String notes
String subtotal
String discountpercent
String discountamount
String total
String paid
String totaldue
}
問題:
セッションを開こうとすると、クラスが見つかりません。
Configuration hibernateConfig = new Configuration();
Properties hibernateConfigProps = hibernateConfig.getProperties();
hibernateConfigProps.put("hibernate.classLoader.application", gcl);
hibernateConfig.setProperties(hibernateConfigProps);
SessionFactory sf = hibernateConfig.configure(new File("hibernate.config.xml")).buildSessionFactory();
Session sess = sf.openSession();
原因: org.hibernate.MappingException: Hibernate 構成エントリで宣言されたクラス [invoice] を読み込めません。
hibernate.classLoader.application プロパティを GroovyClassLoader インスタンスに設定してから、構成でプロパティを設定しようとしましたが、うまくいきませんでした。
私の検索では、org.hibernate.service.classloading.spi.ClassLoaderService を使用する必要があるかもしれないことがわかりましたが、Hibernate でこれを行う方法がわかりません。
スタックトレースについては、以下を参照してください。
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.simontuffs.onejar.Boot.run(Boot.java:342)
at com.simontuffs.onejar.Boot.main(Boot.java:168)
Caused by: org.hibernate.MappingException: Unable to load class [ invoice] declared in Hibernate configuration <mapping/> entry
at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:2139)
at org.hibernate.cfg.Configuration.parseSessionFactory(Configuration.java:2087)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:2067)
at org.hibernate.cfg.Configuration.doConfigure(Configuration.java:2020)
at org.hibernate.cfg.Configuration.configure(Configuration.java:1993)
at com.referencelogic.xmlormupload.main.XmlormuploadMain.run(XmlormuploadMain.java:101)
at com.referencelogic.xmlormupload.main.XmlormuploadMain.main(XmlormuploadMain.java:54)
... 6 more
Caused by: java.lang.ClassNotFoundException: invoice
at com.simontuffs.onejar.JarClassLoader.findClass(JarClassLoader.java:713)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at com.simontuffs.onejar.JarClassLoader.loadClass(JarClassLoader.java:630)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:186)
at org.hibernate.internal.util.ReflectHelper.classForName(ReflectHelper.java:192)
at org.hibernate.cfg.Configuration.parseMappingElement(Configuration.java:2136)
... 12 more
スレッドのコンテキスト クラス ローダーの設定を提案どおりに試みましたが、Hibernate はそれを無視しています。
ClassLoader oldcl = Thread.currentThread().getContextClassLoader();
System.out.println("Old classloader is " + oldcl);
Thread.currentThread().setContextClassLoader(gcl);
ClassLoader newcl = Thread.currentThread().getContextClassLoader();
System.out.println("New classloader is " + newcl);
Configuration hibernateConfig = new Configuration();
System.out.println("Hibernate config class loader is: " + hibernateConfig.getClass().getClassLoader());
結果は
Old classloader is com.simontuffs.onejar.JarClassLoader@5c58d6b0
New classloader is groovy.lang.GroovyClassLoader@3ed4b480
Hibernate config class loader is: com.simontuffs.onejar.JarClassLoader@5c58d6b0
前述のスタック トレースが続きます。
助言がありますか?