我正在尝试从几个 jar 文件加载实体。我设法做的是
配置休眠
private void configure(File[] moduleFiles)
{
Configuration configuration = new Configuration()
.setProperty("hibernate.connection.url", getConnectionString())
.setProperty("hibernate.connection.username", "user")
.setProperty("hibernate.connection.password", "pass")
.setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbc.JDBCDriver")
.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect")
.setProperty("hibernate.archive.autodetection", "class,hbm")
.setProperty("exclude-unlisted-classes", "false")
.setProperty("hibernate.hbm2ddl.auto", "update");
if (moduleFiles != null) {
for (File f : moduleFiles) {
configuration.addJar(f);
}
}
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
this.sessionFactory = configuration.buildSessionFactory(serviceRegistry);
}
Run Code Online (Sandbox Code Playgroud)所以实体应该从 moduleFiles 数组加载。在日志中我可以看到:
2015-08-25 20:52:12 INFO Configuration:837 - HHH000235: Searching for mapping documents in jar: ProgramInfo.jar
2015-08-25 20:52:12 INFO Configuration:837 - HHH000235: Searching for mapping documents in jar: SampleModule.jar
Run Code Online (Sandbox Code Playgroud)
外部 jar 中的实体
@Entity
@Table(name = "PROGRAMINFO_DATA", schema = "PUBLIC", catalog = "PUBLIC")
@NamedQueries({@NamedQuery(name = "PrograminfoDataEntity.findByWindowInfo", query = "FROM PrograminfoDataEntity WHERE PROCESSPATH = :pp AND WINDOWTITLE = :wt AND DAY = :d")})
public class PrograminfoDataEntity implements SVEntity {
private long id;
private Date day;
private String processname;
private String processpath;
private String programname;
private String windowtitle;
// getters setters etc.
}
Run Code Online (Sandbox Code Playgroud)外部jar中的persistence.xml(META-INF目录)
<persistence-unit name="ProgramInfoPersistenceUnit">
<class>com.antara.modules.programinfo.db.model.PrograminfoDataEntity</class>
</persistence-unit>
Run Code Online (Sandbox Code Playgroud)
查询上述实体用法
Session session = openSession();
Query q = session.getNamedQuery("PrograminfoDataEntity.findByWindowInfo");
q.setParameter("pp", windowInfo.getProcessPath());
q.setParameter("wt", windowInfo.getWindowTitle());
q.setDate("d", date);
PrograminfoDataEntity result = (PrograminfoDataEntity) q.uniqueResult();
closeSession(session);
Run Code Online (Sandbox Code Playgroud)抛出异常:
org.hibernate.MappingException: Named query not known: PrograminfoDataEntity.findByWindowInfo
at org.hibernate.internal.AbstractSessionImpl.getNamedQuery(AbstractSessionImpl.java:177)
at org.hibernate.internal.SessionImpl.getNamedQuery(SessionImpl.java:1372)
at com.antara.modules.programinfo.db.dao.PrograminfoDao.findByWindowInfo(PrograminfoDao.java:26)
at com.antara.modules.programinfo.ProgramInfoImpl.run(ProgramInfoImpl.java:84)
Run Code Online (Sandbox Code Playgroud)
问题是为什么 hibernate 没有从 jar 加载带注释的实体?异常不仅由命名查询引发,而且由实体的任何其他操作引发。在使用这个实体之前没有错误。本地实体已正确加载。
编辑:
经过一些更改后,我设法通过 Hibernate 识别实体
DEBUG AnnotationBinder:601 - Binding entity from annotated class: com.antara.modules.programinfo.db.model.PrograminfoDataEntity
DEBUG QueryBinder:93 - Binding named query: PrograminfoDataEntity.findByWindowInfo => FROM PrograminfoDataEntity ....
Run Code Online (Sandbox Code Playgroud)
但是当我尝试使用实体时,我仍然遇到异常:
ERROR AssertionFailure:61 - HHH000099: an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): java.lang.ClassNotFoundException: com.antara.modules.programinfo.db.model.PrograminfoDataEntity
ERROR Main:114 - PersistentClass name cannot be converted into a Class
...
Caused by: java.lang.ClassNotFoundException: com.antara.modules.programinfo.db.model.PrograminfoDataEntity
Run Code Online (Sandbox Code Playgroud)
更改是:将配置传递给 jar 内的每个“模块”并添加带注释的类(模块是指在启动时调用方法的 SPI 服务)
@Override
public void configureDB(Configuration configuration) {
configuration.addAnnotatedClass(PrograminfoDataEntity.class);
}
Run Code Online (Sandbox Code Playgroud)
经过 3 天的试验,我找到了解决方案:Hibernate 通过 ContextClassLoader 使用反射机制加载类
Thread.currentThread().getContextClassLoader();
Run Code Online (Sandbox Code Playgroud)
所以我将 ContextClassLoader 设置为 PrograminfoDataEntity 的 ClassLoader
Thread.currentThread().setContextClassLoader(PrograminfoDataEntity.class.getClassLoader());
Run Code Online (Sandbox Code Playgroud)
它解决了所有 NoClassDefFound、ClassCastException 和类似的错误
| 归档时间: |
|
| 查看次数: |
5061 次 |
| 最近记录: |