休眠条件查询到 JPA 条件查询

Posted

技术标签:

【中文标题】休眠条件查询到 JPA 条件查询【英文标题】:Hibernate criteria queries to JPA criteria queries 【发布时间】:2017-12-20 10:15:08 【问题描述】:

我正在迁移到 Hibernate 5.2,并且由于不推荐使用 createCriteria,我们计划将查询重写为 JPA 样式。 我面临一个问题(java.lang.IllegalArgumentException:不是实体),其中相同的代码正在使用休眠标准方法。

使用休眠标准

Criteria criteria = getSession().createCriteria(className);

for (Map.Entry<String, Object> entry : matchingCriteria.entrySet()) 
    criteria.add(Expression.eq(entry.getKey(), entry.getValue()));

List objsMatchingCriteria = criteria.list();

获取 JPA 标准的“java.lang.IllegalArgumentException: Not an entity”

CriteriaBuilder cb = getSession().getCriteriaBuilder();
CriteriaQuery  cq = cbuilder.createQuery(refClassName);
Root root = cquery.from(refClassName);
cq.select(root);
List<Predicate> predicates = new ArrayList<>();
for (Map.Entry<String, Object> entry : matchingCriteria.entrySet()) 
    predicates.add(cb.equal(root.get(entry.getKey()), entry.getValue()));

cq.where(predicates.toArray(new Predicate[predicates.size()]));

List objsMatchingCriteria = 
    getSession().createQuery(cq).getResultList();

你能告诉我JPA代码有什么问题吗

更新 当我们有基类(抽象)并且实际的实体类是具体的子类时会看到这个问题。早先使用hibernate条件,即使我通过了基类,检索结果也没有问题。

但是在迁移到 JPA 标准后,我无法通过基类。这可以在 JPA 中管理吗?

提前致谢。

【问题讨论】:

什么是 refClassName?你应该使用泛型。 refClassName 是 Class 对象。 (例如 Employee.class)。我正在根据类名加载类。类 refClassName = null;尝试 refClassName = Class.forName(className); 捕捉 (ClassNotFoundException cnf) cnf.printStackTrace(); 遇到异常时传递的是哪种类型?你能发布堆栈跟踪吗 您可能必须将您的实体包含在 persistence.xml 中,例如参见 ***.com/questions/1780341/… 我正在传递 com.xxxx.xxxx.xxxx.xxxx.Neighbor。 Stacktrace 是:java.lang.IllegalArgumentException:不是实体:org.hibernate.metamodel.internal.MetamodelImpl.entity(MetamodelImpl.java:456) 的 org.hibernate.query 的类 com.xxxx.xxxx.xxxx.xxxx.Neighbor .criteria.internal.QueryStructure.from(QueryStructure.java:126) at org.hibernate.query.criteria.internal.CriteriaQueryImpl.from(CriteriaQueryImpl.java:153) 【参考方案1】:

如果您在 hibernate 中使用注解,那么您将在 refClass 上定义一个 @Entity。就像你必须像这样映射实体:

@Entity
@Table(name = "tableName")
public class ClassOfTable implements Serializable,Cloneable 

  public ClassOfTable () 
  

  @Column(name = "column1")
  private Boolean member1;

  @Column(name = "column2")
  private String member2;


您将在创建sessionFactory 时通过此类。如果你在创建 sessionFactory 时没有传递这个类,那么它将抛出一个异常,该类不是实体。

StandardServiceRegistry standardRegistry =
        new StandardServiceRegistryBuilder().applySettings(createProperties(
            host, port, dbName, protocol, userName, password, minPoolSize, maxPoolSize)
            .getProperties()).build();

    MetadataSources sources = new MetadataSources(standardRegistry);
    annotatedClassNames.add(refClass.class);
    Metadata metaData = sources.getMetadataBuilder().build();
    return metaData.getSessionFactoryBuilder().build();

或者如果您使用 Hibernate 配置文件,那么您必须在 hibernate.cfg.xml 中指定 hbm.xml 的映射文件名,并且您的 someName.hbm.xml 包含 refClass 的映射。

然后创建会话工厂。

            Configuration configuration = new Configuration();
            configuration.configure("hibernate.cfg.xml");
            StandardServiceRegistryBuilder s-s-rb = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
            SessionFactory sessionFactory = configuration.buildSessionFactory(s-s-rb.build());
            Session session = sessionFactory.openSession();

您的 hibernate.cfg.xml 必须包含定义您的 refClass 映射的(映射资源)条目。

<hibernate-configuration>
    <session-factory>
        <!-- JDBC connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost/mediadb</property>
        <property name="connection.username">kodejava</property>
        <property name="connection.password">kodejava123</property>



        <!-- Mapping to hibernate mapping files -->
        <mapping resource="org/kodejava/example/hibernate/model/someName.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

而且你的 hbm.xml 必须有 refClass 映射

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "refClass" table = "some Class">

      <meta attribute = "class-description">
         This class contains the some detail. 
      </meta>

      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>

      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>

   </class>

【讨论】:

以上是关于休眠条件查询到 JPA 条件查询的主要内容,如果未能解决你的问题,请参考以下文章

休眠条件查询返回过时的结果

Jpa , Hibernate 选择查询优化

SQL 左外连接查询到 JPA 条件的转换

JPA分页查询与条件分页查询

休眠查询语言或使用条件?

带有投影和限制的休眠条件查询问题