JPA 实体未在 EntityManager 中注册
JPA Entity not registered with EntityManager
我一直在使用 Guice 实现模块化体系结构应用程序,每个应用程序模块都分成单独的 eclipse 项目并拥有自己的 Guice 模块。我在注册不在 JPA 持久性项目中的 JPA 实体时遇到了问题。项目里面的注册没问题,其他项目上的就不行。在单个项目和单个 Guice 模块上实现应用程序时没有问题。
配置似乎没问题,但很可能是我遗漏了什么。
这是我在尝试从数据库中获取实体时遇到的错误:
Caused by: java.lang.IllegalArgumentException: Not an entity: class org.gradle.security.persistence.jpa.entities.impl.SubjectImpl
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
at org.hibernate.jpa.criteria.QueryStructure.from(QueryStructure.java:139)
at org.hibernate.jpa.criteria.CriteriaQueryImpl.from(CriteriaQueryImpl.java:173)
at org.gradle.security.pbeingersistence.jpa.dao.impl.SubjectDAOImpl.findByPrincipal(SubjectDAOImpl.java:48)
下面的 SubjectDAOImpl 和最后一行尝试获取实体时的错误,
public Subject findByPrincipal(String principal, LockModeType lockMode) {
CriteriaQuery<SubjectImpl> criteria = criteriaQuery(SubjectImpl.class);
CriteriaBuilder cb = getEM().getCriteriaBuilder();
Root<SubjectImpl> activation = criteria.from(SubjectImpl.class);
....
SubjectImpl 为:
@Entity
@Audited
@Table(name=SubjectImpl.TABLE_NAME, schema=Config.Schemas.DEFAULT)
public class SubjectImpl extends BaseEntityImpl implements Subject {
public static final String TABLE_NAME = Config.TABLE_PREFIX + "subject";
@Basic(optional = false)
@Column(name = "principal", unique = true)
protected String principal;
......
}
Guice模块配置如下:
安全模块:
private static class SecurityModule extends AbstractModule {
@Override
protected void configure() {
bind(Subject.class).to(SubjectImpl.class).asEagerSingleton();
...
bind(SubjectDAO.class).to(SubjectDAOImpl.class).asEagerSingleton();
}
}
持久化模块:
public class JPAPersistenceModule extends AbstractModule implements ArchetypeModule {
@Override
protected void configure() {
try {
Properties props = new Properties();
InputStream is = new FileInputStream(
this.getClass().getClassLoader().getResource(PersistenceProperties.DEFAULT_PROPERTIES_FILE).getPath());
props.load(is);
Names.bindProperties(binder(), props);
bind(PersistenceProperties.class).asEagerSingleton();
JpaPersistModule persistModule = new JpaPersistModule(PersistenceProperties.PERSISTENCE_UNIT);
persistModule.properties(props);
install(persistModule);
} catch (IOException e) {
LOGGER.error("Could not load persistence module: ", e);
System.exit(-1);
}
}
和服务器模块:
public class ServerModule extends JerseyServletModule implements ArchetypeModule {
@Override
protected void configureServlets() {
filter("/*").through(PersistFilter.class);
serve("/rest","/rest/*").with(GuiceContainer.class);
}
}
Guice 模块按以下顺序安装:JPAPersistenceModule、SecurityModule、ServerModule。
无法解决这个问题,你能帮帮我吗?
在与使用相同架构和类似技术实现项目的朋友交谈后,我发现原因是由于 JPA Hibernate 限制。与许多其他注释不同,JPA 实现的注释只能在实现 Guice 持久化模块的项目上检测到。
此问题的解决方法是使用反射捕获所有带有注释的 类(Reflections 库为您完成此操作)并将其传递给 properties 参数上的 Guice JpaPersistModule。
结果应该与此有些相似:
props.put(org.hibernate.jpa.AvailableSettings.LOADED_CLASSES, Lists.newArrayList(EntityLoader.loadEntities()));
JpaPersistModule persistModule = new JpaPersistModule(PersistenceProperties.PERSISTENCE_UNIT);
persistModule.properties(props);
install(persistModule);
我一直在使用 Guice 实现模块化体系结构应用程序,每个应用程序模块都分成单独的 eclipse 项目并拥有自己的 Guice 模块。我在注册不在 JPA 持久性项目中的 JPA 实体时遇到了问题。项目里面的注册没问题,其他项目上的就不行。在单个项目和单个 Guice 模块上实现应用程序时没有问题。
配置似乎没问题,但很可能是我遗漏了什么。 这是我在尝试从数据库中获取实体时遇到的错误:
Caused by: java.lang.IllegalArgumentException: Not an entity: class org.gradle.security.persistence.jpa.entities.impl.SubjectImpl
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
at org.hibernate.jpa.criteria.QueryStructure.from(QueryStructure.java:139)
at org.hibernate.jpa.criteria.CriteriaQueryImpl.from(CriteriaQueryImpl.java:173)
at org.gradle.security.pbeingersistence.jpa.dao.impl.SubjectDAOImpl.findByPrincipal(SubjectDAOImpl.java:48)
下面的 SubjectDAOImpl 和最后一行尝试获取实体时的错误,
public Subject findByPrincipal(String principal, LockModeType lockMode) {
CriteriaQuery<SubjectImpl> criteria = criteriaQuery(SubjectImpl.class);
CriteriaBuilder cb = getEM().getCriteriaBuilder();
Root<SubjectImpl> activation = criteria.from(SubjectImpl.class);
....
SubjectImpl 为:
@Entity
@Audited
@Table(name=SubjectImpl.TABLE_NAME, schema=Config.Schemas.DEFAULT)
public class SubjectImpl extends BaseEntityImpl implements Subject {
public static final String TABLE_NAME = Config.TABLE_PREFIX + "subject";
@Basic(optional = false)
@Column(name = "principal", unique = true)
protected String principal;
......
}
Guice模块配置如下:
安全模块:
private static class SecurityModule extends AbstractModule {
@Override
protected void configure() {
bind(Subject.class).to(SubjectImpl.class).asEagerSingleton();
...
bind(SubjectDAO.class).to(SubjectDAOImpl.class).asEagerSingleton();
}
}
持久化模块:
public class JPAPersistenceModule extends AbstractModule implements ArchetypeModule {
@Override
protected void configure() {
try {
Properties props = new Properties();
InputStream is = new FileInputStream(
this.getClass().getClassLoader().getResource(PersistenceProperties.DEFAULT_PROPERTIES_FILE).getPath());
props.load(is);
Names.bindProperties(binder(), props);
bind(PersistenceProperties.class).asEagerSingleton();
JpaPersistModule persistModule = new JpaPersistModule(PersistenceProperties.PERSISTENCE_UNIT);
persistModule.properties(props);
install(persistModule);
} catch (IOException e) {
LOGGER.error("Could not load persistence module: ", e);
System.exit(-1);
}
}
和服务器模块:
public class ServerModule extends JerseyServletModule implements ArchetypeModule {
@Override
protected void configureServlets() {
filter("/*").through(PersistFilter.class);
serve("/rest","/rest/*").with(GuiceContainer.class);
}
}
Guice 模块按以下顺序安装:JPAPersistenceModule、SecurityModule、ServerModule。 无法解决这个问题,你能帮帮我吗?
在与使用相同架构和类似技术实现项目的朋友交谈后,我发现原因是由于 JPA Hibernate 限制。与许多其他注释不同,JPA 实现的注释只能在实现 Guice 持久化模块的项目上检测到。
此问题的解决方法是使用反射捕获所有带有注释的 类(Reflections 库为您完成此操作)并将其传递给 properties 参数上的 Guice JpaPersistModule。 结果应该与此有些相似:
props.put(org.hibernate.jpa.AvailableSettings.LOADED_CLASSES, Lists.newArrayList(EntityLoader.loadEntities()));
JpaPersistModule persistModule = new JpaPersistModule(PersistenceProperties.PERSISTENCE_UNIT);
persistModule.properties(props);
install(persistModule);