Hibernate / JPA - 访问SingularAttribute参数时出现NullPointerException
我正在尝试使用Hibernate 5.0.7.Final的JPA2类型安全条件查询。
I'm trying to use JPA2 type-safe criteria queries with Hibernate 5.0.7.Final.
...
criteria.where( builder.equal( root.get(SingularAttribute.attr), value ));
//where parameters are
//criteria.where( builder.equal( root.get(Person_.name), "Can" ));
...
root.get总是抛出 NullPointerException
。 org.hibernate.jpamodelgen生成
。人
的元模型类 Person _
.JPAMetaModelEntityProcessor
The root.get always throw NullPointerException
.
The metamodel class Person_
for Person
is generated by org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
.
在 JPA / Hibernate静态元模型属性未填充 - NullPointerException 但这次两个类都在同一个包中。
A similar problem was asked in JPA/Hibernate Static Metamodel Attributes not Populated -- NullPointerException but this time both classes are in the same package.
堆栈跟踪:
java.lang.NullPointerException
at org.hibernate.jpa.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:123)
我的代码:
用于确保它们具有 getId();
的接口。
Interface that i use to make sure they will have getId();
.
package it.unibz.db.hibernate.model;
public interface ModelInterface<PK extends Serializable> extends Serializable {
PK getId();
}
模型类
package it.unibz.db.hibernate.model;
@Entity
@Table(name ="person")
public class Person implements ModelInterface<Integer> {
@Id
private Integer id;
private String name;
public Integer getId() {
return id;
}
//other getter and setters
}
生成metamodel Person_ class
Generated metamodel Person_ class
package it.unibz.db.hibernate.model;
@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor")
@StaticMetamodel(Person.class)
public abstract class Person_ {
public static volatile SingularAttribute<Person, String> name;
public static volatile SingularAttribute<Person, Integer> id;
}
我用PersonDao继承的通用DAO类
Generic DAO class that i inherit with PersonDao
public class GenericDao<E extends ModelInterface<PK>, PK extends Serializable> implements DaoInterface<E, PK> {
private Class<E> type;
public GenericDao(Class<E> type) {
this.type = type;
//called as super(ClassName.class); eg. super(Person.class);
}
public List<E> readBy(SingularAttribute column, String value) throws Exception {
EntityManager em = HibernateUtil.getEntityManager();
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<E> criteria = builder.createQuery(type);
Root<E> root = criteria.from(type);
criteria.select(root);
criteria.where( builder.equal( root.get(column), value ));
List<E> entityList = em.createQuery(criteria).getResultList();
em.close();
return entityList;
}
}
我的一些依赖项
-
hibernate-c3p0 5.0.7.Final
hibernate-c3p0 5.0.7.Final
hibernate-entitymanager 5.0.7 .Final
hibernate-entitymanager 5.0.7.Final
postgresql 9.4.1207.jre7
postgresql 9.4.1207.jre7
hibernate-jpamodelgen 5.0.7 .Final
hibernate-jpamodelgen 5.0.7.Final
编辑:
在main方法中运行此代码
Running this code in the main method works
EntityManager em = HibernateUtil.getEntityManager();
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
Root<Person> root = criteria.from(Person.class);
criteria.select(root);
criteria.where( builder.equal( root.get(Person_.name), "Can" ));
List<Person> entityList = em.createQuery(criteria).getResultList();
//do stuff with entityList
,但方法中包含的相同代码会抛出 NullPointerException
。
but the same code covered in a method throws NullPointerException
.
public List<Person> readBy(SingularAttribute column, String value) throws Exception {
log.debug("Reading entity by");
EntityManager em = HibernateUtil.getEntityManager();
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
Root<Person> root = criteria.from(Person.class);
criteria.select(root);
criteria.where( builder.equal( root.get(column), value ));
List<Person> entityList = em.createQuery(criteria).getResultList();
em.close();
return entityList;
}
所以似乎问题是传递 SingularAttribute
方法的参数 readBy(SingularAttribute列,字符串值)
。
So it seems that the problem is passing SingularAttribute
parameter to the method readBy(SingularAttribute column, String value)
.
我测试了这个main中的代码打印 false
I tested this code in main and this prints false
EntityManager em = HibernateUtil.getEntityManager();
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
Root<Person> root = criteria.from(Person.class);
System.out.println(root.get(Person_.name) == null); //false
同时抛出 InvocationTargetException
导致by NullPointerException
at root.get(column)
。
meanwhile this throws InvocationTargetException
caused by NullPointerException
at root.get(column)
.
//invoked as personDao.test(Person_.name) from main
public void test(SingularAttribute column) {
EntityManager em = HibernateUtil.getEntityManager();
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
Root<Person> root = criteria.from(Person.class);
System.out.println(root.get(column) == null); //InvocationTargetException
}
这是它应该做的吗?如何将 SingularAttribute
对象作为参数传递给方法?
Is this what it's supposed to do? How can i pass SingularAttribute
object to a method as a parameter?
在方法调用以某种方式工作之前,在main中调用 HibernateUtil.getEntityManager()
。 它甚至可以在我称之为方法的空块 init()
。
它可能与类的初始化有关。这是代码片段。
Calling HibernateUtil.getEntityManager()
in main before method call somehow works. It even works when i call literally a empty block of a method init()
.
It could be related with initialization of classes. Here's the code snippet.
public class HibernateUtil {
private static EntityManagerFactory emFactory;
private static EntityManager em;
private static final Logger log = LoggerFactory.getLogger(HibernateUtil.class);
private static final String PERSISTENCE_UNIT = "pt";
static{
log.info("Creating entity manager factory");
emFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT);
}
//calling this from main before PersonDao's method calls somehow works...
public void init(){} //does nothing
public static EntityManager getEntityManager(){
if(em != null && em.isOpen()){
closeEntityManager();
}
log.debug("Creating new entity manager");
em = emFactory.createEntityManager();
return em;
}
public static void close() throws Exception {
if(em != null && em.isOpen()){
closeEntityManager();
}
log.info("Closing entity manager factory");
emFactory.close();
}
private static void closeEntityManager(){
log.info("Closing last entity manager");
em.close();
}
}