Hibernate条件查询JPA条件查询

时间:2017-12-20 10:15:09

标签: java hibernate jpa

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

使用休眠标准

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:非实体”

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中管理。

提前致谢。

1 个答案:

答案 0 :(得分:0)

如果您在休眠模式下使用注释,则将在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 ssrb = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
            SessionFactory sessionFactory = configuration.buildSessionFactory(ssrb.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>