Hibernate jpql查询正确用法

时间:2016-08-21 06:59:25

标签: java mysql hibernate jersey dropwizard

我正在使用JerseyHibernate创建Dropwizard网络服务。

我想要求一种正确有效的方法来使用它们来连接和使用数据库。

我已经定义了数据库本身。我想问一下添加记录和查询数据库的正确方法。

关于查询数据库,现在我在注释@NamedQueries中得到了一些简单的JPQL查询,这是表示数据库表的类的一部分。例如:

@XmlRootElement
@Entity(name = "Persons")
@Table(name = "Persons")
@NamedQueries(
        { 
        @NamedQuery(name = "Person.findAll", query = "select p from Persons p"),
        @NamedQuery(name = "Person.findByEmail", query = "select p from Persons p " + "where p.personEmail like :email") 
        })

public class Person implements Serializable
{ ... }

当我想查询时,我正在做这样的事情:

public Person getPersonByEmail(String email)
{
        Person personByName = (Person) namedQuery("Person.findByEmail").setParameter("email", email).uniqueResult();
        return personByName;
}

这是查询数据库的正确有效方法吗?我应该在@NamedQueries注释中堆叠这样的查询吗?

关于添加到数据库,我现在这样做:

public void insertPersonToDB()
    {
        Session session = sessionFactory.openSession();
        Transaction tx = null;

        try
        {
            tx = session.beginTransaction();
            Person pers = new Person("param1","param2");
            short personID = (short) session.save(pers);
            tx.commit();
        }
        catch (HibernateException e)
        {
            if (tx != null) tx.rollback();
            e.printStackTrace();
        }
        finally
        {
            session.close();
        }
}

这也是向DB添加记录的正确有效方法吗?

1 个答案:

答案 0 :(得分:1)

  

当我想查询时,我正在做这样的事情:

public Person getPersonByEmail(String email){
        Person personByName = (Person) namedQuery("Person.findByEmail").setParameter("email", email).uniqueResult();
        return personByName;
}
  

这是查询数据库的正确有效方法吗?我应该堆叠   像@NamedQueries注释那样的查询?

另一种方法是使用createQuery(jpqlQuery)

public Person getPersonByEmail(String email){
        Person personByName = (Person) em.createQuery(
        "select p from Persons p where p.personEmail like :email"). 
        setParameter("email", email).getSingleResult();
        return personByName;
}

我们有时会调用使用createQuery()动态查询创建的查询,因为没有编译 您也可以使用Criteria(用于创建查询的完整对象方式),但编写起来比较复杂,因此对于" true"动态查询,其中在运行时添加查询的某些子句(例如,添加条件或连接)。

通常,如果您的请求不需要以动态方式创建(在运行时添加SQL子句),通常会建议您使用@NameQuery而不是createQuery(java.lang.String jpqlString),因为我们认为更多高性能。就个人而言,我认为这是一个错误的好建议。

例如,在 Pro EJB 3:Java Persistence API 中,您被称为Named queries are a way of organising your static queries in a manner that is more readable, maintainable as well as performant.

为了表现,这是理论上的 它指的是从HQL到SQL的转换。
使用NamedQuery,您确定它只执行了一次 但是对于createQuery(java.lang.String jpqlString),如果你做得好的话,有效表现是相同或几乎相同的。

首先,如果将HQL查询转换为SQL,则将其与将数据传输到数据库,执行并检索结果(sql映射到对象映射)的成本进行比较几乎没有任何意义。 其次,大多数查询引擎(例如Hibernate)将缓存已翻译的SQL,但如果您构建查询,则不应该:用于设置查询参数的字符串连接。

对于余数,createQuery(java.lang.String jpqlString)有助于创建一个好的设计,因为它显然更容易阅读和修改查询的位置,而不是实体的根。登记/> 没有间接性来读取它的全局性,也看看如何在查询中设置参数 相反,在类的根目录中修改JPQL查询可能看起来很像并且具有非常接近的名称,这很容易出错。

JPQL的唯一真正优势是在编译时,可能会检测到查询中的语法错误,因此会快速停止构建。

编辑:问题的第二部分

关于添加到数据库,我现在这样做:

NamedQuery
  

这也是向DB添加记录的正确有效方法吗?

几乎正确。您应该登录public void insertPersonToDB() { Session session = sessionFactory.openSession(); Transaction tx = null; try { tx = session.beginTransaction(); Person pers = new Person("param1","param2"); short personID = (short) session.save(pers); tx.commit(); } catch (HibernateException e) { if (tx != null) tx.rollback(); e.printStackTrace(); } finally { session.close(); } } 以进行调试,如果回滚失败,您还应该记录并抛出异常。

catch HibernateException