Hibernate使用HQL,Criteria和Native SQL查询,哪个好?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate使用HQL,Criteria和Native SQL查询,哪个好?相关的知识,希望对你有一定的参考价值。

或者是什么情况下使用什么,求熟手来解答!

参考技术A hql提供了更接近于传统SQL语句的查询语法,容易过度吧,官方推荐使用,它提供强大的查询功能。一般使用这种查询。
Criteria查询,可移植性好,用起来也很方便,当你的查询条件很多时,可用Example创建一查询依据,查出属性与之类似的对象,代码简洁运用很方便。
Native
SQL一般在遇到很复杂的查询条件时使用,

Hibernate:Criteria 和 HQL 的映射行为之间的区别

【中文标题】Hibernate:Criteria 和 HQL 的映射行为之间的区别【英文标题】:Hibernate: Difference between mapping behaviour of Criteria and HQL 【发布时间】:2018-08-05 21:29:40 【问题描述】:

Hibernate 和 HQL 的 Criteria API 在加载类映射方面表现不同。 如果我从 XML 加载映射,两种方式都可以加载 Entity 类。但是,如果我使用注释,则只有 Criteria api 能够加载映射。请帮助我了解原因。

我使用的是 Hibernate 版本:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>4.3.11.Final</version>
</dependency>

休眠配置

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/demo</property>
        <property name="hibernate.connection.username">user</property>
        <property name="hibernate.connection.password">password</property>
        <property name="hibernate.connection.pool_size">1</property>
        <property name="hibernate.current_session_context_class">thread</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.archive.autodetection">class, hbm</property>

        <!--<mapping  class="com.mk.hibernate.User" resource="User.hbm.xml"/>-->
        <mapping class="com.mk.hibernate.User"/>
    </session-factory>
</hibernate-configuration>

休眠映射文件:

<?xml version="1.0" encoding="UTF-8"?>

<hibernate-mapping
                   xmlns="http://www.hibernate.org/xsd/hibernate-mapping"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://www.hibernate.org/xsd/hibernate-mapping
        http://www.hibernate.org/xsd/hibernate-mapping/hibernate-mapping-4.0.xsd">

    <class name="com.mk.hibernate.User" table="USERS">
        <id name="username" column="USERNAME" type="java.lang.String" >
            <generator class="assigned"></generator>
        </id>
        <property name="firstname" column="FIRSTNAME" type="java.lang.String"/>
        <property name="lastname" column="LASTNAME" type="java.lang.String"/>
        <property name="doj" column="DOJ" type="java.util.Date"/>
    </class>

</hibernate-mapping>

我有一个实体

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import java.util.Date;
import java.util.Objects;

@Entity(name = "USERS")
public class User implements java.io.Serializable 
    @Id
    @Column(name = "USERNAME")
     private String username;
    @Column(name = "FIRSTNAME")
     private String firstname;
    @Column(name = "LASTNAME")
     private String lastname;
    @Column(name = "DOJ")
     private Date doj;
...
...

我有两种方法来获取这个实体的数据

public List<User> getAllUsersByCriteria() 
        Session session = sessionFactory.openSession();
        Criteria cr = session.createCriteria(User.class);
        List<User> users = cr.list();
        System.out.println(users.size());
        session.close();
        return users;
    

 public List<User> getAllUsers() 
        Session session = sessionFactory.openSession();
        List<User> users = session.createQuery(" from User").list();
        session.close();
        return users;
    

当我执行以下代码时

        System.out.println("====By Criteria===");
        controller.getAllUsersByCriteria().forEach(u -> 
            System.out.println(u.getFirstname());
        );
        System.out.println("====By Query===");
        controller.getAllUsers().forEach(u -> 
            System.out.println(u.getFirstname());
        );

我收到以下异常

====By Criteria===
Hibernate: select this_.USERNAME as USERNAME1_0_0_, this_.DOJ as DOJ2_0_0_, this_.FIRSTNAME as FIRSTNAM3_0_0_, this_.LASTNAME as LASTNAME4_0_0_ from USERS this_
2
User1
User2
====By Query===
problem creating session factory!
org.hibernate.hql.internal.ast.QuerySyntaxException: User is not mapped [ from User]
    at org.hibernate.hql.internal.ast.QuerySyntaxException.generateQueryException(QuerySyntaxException.java:96)
    at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:120)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:234)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:131)
    at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:93)
    at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:167)
    at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:301)
    at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:236)
    at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1836)
    at com.mk.hibernate.UserServiceImpl.getAllUsers(UserServiceImpl.java:33)
    at com.mk.hibernate.UserControllerImpl.getAllUsers(UserControllerImpl.java:27)
    at Main.main(Main.java:35)
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: User is not mapped
    at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:189)
    at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:109)
    at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromClause.java:95)
    at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlWalker.java:338)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3678)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3567)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:708)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:564)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:301)
    at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:249)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278)
    at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
    ... 10 more
Feb 26, 2018 5:32:27 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
INFO: HHH000030: Cleaning up connection pool [jdbc:mysql://localhost:3306/demo]

【问题讨论】:

有道理... 没有得到它。为什么会这样? 无论如何,您应该只在会话期间访问持久对象。 你是否在你的 User.hbm.xml 中指定了一个包? 添加了映射文件。我在那里指定具有完全限定名称的类。 【参考方案1】:

我认为您误解了 @Entity 注释的 name 属性应该如何工作。

@Entity(name = "USERS") 将 User 实体的 hql 名称映射到 USERS,如果不存在值,则默认为类名。因此,一个有效的 hql 查询将是 "from USERS" 而不是 "from User"

您希望注解@Table(name = "USERS") 定义实体的表名。

尝试将映射注释更改为以下内容:

@Entity
@Table(name = "USERS")
public class User implements java.io.Serializable 
....

【讨论】:

啊..谢谢。我知道我错过了一些愚蠢的东西。只是快速输入,完全错过了看到它。【参考方案2】:

试试这个只是改变类名,它对我有用::

List<University> users = entityManager.createQuery(" from University").getResultList();
 System.out.println("University size = " + users.size());
 for (University university : users) 
    System.out.println("University Name = " + university.getName());

【讨论】:

以上是关于Hibernate使用HQL,Criteria和Native SQL查询,哪个好?的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate HQL,Criteria和SQL

Hibernate使用HQL,Criteria和Native SQL查询,哪个好?

hibernate之HQL,Criteria与SQL

grails的criteria和hql查询

hibernate框架学习笔记7:HQL查询Criteria查询

Hibernate的DetachedCriteria使用(含Criteria)