Hibernate jpql查询正确用法

Hibernate jpql query correct usage

我正在使用 HibernateDropwizard 创建一个 Jersey 网络服务。

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

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

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

@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();
        }
}

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

When I want to query I am doing something like this:

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

Is this a correct and effective way of querying the DB? should I stack queries like that in the @NamedQueries annotation?

另一种方法是使用 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持久化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) 有助于创建良好的设计,因为从调用它的地方读取和修改查询显然比从实体的根目录更容易。
没有间接阅读它的全局性,也没有看到如何在查询中设置参数。
相反,在 class 的根目录下修改许多其他 JPQL 查询中的一个 JPQL 查询很容易出错。[=30] =]

NamedQuery 的唯一真正优势是在编译时,可以检测到查询中的语法错误,从而快速停止构建。

编辑:问题的第二部分

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

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();
        }
}

Is this also a correct and effective way of adding records to the DB?

几乎正确。您应该登录 catch HibernateException 进行调试,如果回滚失败,您还应该登录并抛出异常。

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){
              try {
                     if (tx != null) {
                       tx.rollback();                         
                       logger.error(e);
                      }
                  } catch(Exception e2) {
                     logger.error(e2);
                     throw new RunTimeException("rollback failed", e2);
                  }
             } 
        }
        finally{
            session.close();
        }
}