Hibernate 5.2,如何选择具有给定列值的行?

时间:2017-03-10 23:29:14

标签: java hibernate jpa

我不是SQL新手,但我对Hibernate完全不熟悉。我希望在给定列值的情况下从表中选择丢失的对象将是一项非常简单的任务。但我无法完成它。

我的导师和下面的这个问题都提出了相同的建议,这导致我编写以下代码:JPA: How to get entity based on field value other than ID?

Criteria criteria = session.createCriteria(Competition.class);
List<Competition> list = (List<Competition>) criteria
    .add(Restrictions.eq("Event_EventID", 1)).list();

这样可行,但方法Session.createCriteria()已弃用。由于我刚接触hibernate,我不妨以它的工作方式学习它,所以我不想使用弃用的方法。

官方Hibernate文档只是说使用JPA Criteria。我发现了极其冗长的JPA变种,我觉得这是不可接受的。这个例子是你只需从所有记录中获取完整的对象列表而不需要任何WHERE子句所需的例子......(来自https://www.tutorialspoint.com/jpa/jpa_criteria_api.htm

EntityManagerFactory emfactory = Persistence.createEntityManagerFactory( "Eclipselink_JPA" );
   EntityManager entitymanager = emfactory.createEntityManager( );
   CriteriaBuilder criteriaBuilder = entitymanager.getCriteriaBuilder();
   CriteriaQuery<Object> criteriaQuery = criteriaBuilder.createQuery();
   Root<Employee> from = criteriaQuery.from(Employee.class);

   //select all records
   System.out.println(“Select all records”);
   CriteriaQuery<Object> select = c riteriaQuery.select(from);
   TypedQuery<Object> typedQuery = entitymanager.createQuery(select);
   List<Object> resultlist = typedQuery.getResultList();

如果这是正确的方法,我认为我的标准Preparedstatement方法没有任何优势。这比我见过的任何事情都更冗长,更复杂。

现在,我已经尝试了解有关如何选择对象列表的特定问题,而不是使用5.2中不推荐使用的方法,并避免JPA必须滚动查看完整代码事情,但这就像我得到的那样接近: Hibernate 5.2 version -> A lot of Query methods deprecate?

这让我写了下面的代码:

session.beginTransaction();
List<Competition> list = (List<Competition>) session.createQuery(
    "FROM Competition WHERE Event_EventID = 1").getResultList();

虽然这很有效,而且很简单,但是如果我还有其他东西而不是整数作为变量值,它就会打开SQL注入。我还在代码评论中告诉我,在使用Hibernate时,不需要SQL语法。

毋庸置疑,我有点沮丧,应该这么简单,实际上很难搞清楚。它已弃用,非常冗长或易于SQL注入。有没有人知道我是否遗漏了一些明显的东西,或者在这种情况下Hibernate的设计和/或记录是否很差?

2 个答案:

答案 0 :(得分:0)

  

虽然这很有效,而且很简单,但是如果我还有其他东西而不是整数作为变量值,它就会打开SQL注入。

不,因为您可以将参数传递给查询,就像使用预准备语句一样(并且Hibernate实际上使用带参数的预准备语句)。实际上你可以做更多,因为参数可以命名为:

String jpql = "select e from Event e where e.name = :name";
List<Event> events = 
    em.createQuery(jpql, Event.class)
      .setParameter("name", someNameComingFromAnywhere)
      .getResultList();
  

我还在代码评论中告诉我,在使用Hibernate时,不需要SQL语法。

这不是SQL。这是JPQL(实际上是HQL,JPQL的hibernate版本)。

此处the documentation

你应该考虑使用标准的JPA API而不是专有的Hibernate API。

答案 1 :(得分:0)

首先,这是我如何初始化entityManager:Calling Persistence.createEntityManagerFactory > 1 time

这是如何选择行的示例:

您的实体已映射到表,例如Customer表:

@NamedQueries({
    @NamedQuery(name = Customer.NAMED_QUERY_GET_BY_STATUS, query = "Select e from Customer e where e.status =:status")
 })
@Entity
@Table(name = Customer.TABLE_NAME)
public class Customer {

public static final String TABLE_NAME = "Customer";
public static final String NAMED_QUERY_GET_BY_STATUS = "Customer.getByStatus";

@Id
private Long id;

@Column(name = "status", nullable = false)
private String status;

}

然后使用您在实体类中定义的命名查询来从表中获取所需的行:

public static void main(String[] args){
        EntityManager em = null;
        try{
         JpaUtil.getEntityManager();
            em.getTransaction().begin();
            List<Customer> allNewCustomers = em.createNamedQuery(NAMED_QUERY_GET_BY_STATUS).setParameter("status", "NEW").getResultList();
            em.getTransaction().commit();
        } catch (Exception e){
            //logException
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

编辑:一旦你理解了基础知识,它实际上不会让人感到困惑。 ORM的整个对象是将java对象映射到表。您可以使用注释执行此操作,例如@Table,@ Column等。规范由JPA 2.0规范提供。这些规范由第三方库实现,例如(Hibernate,TopLink等)。有时,这些库为您提供了特定于JPA 2.0规范的实现(hibernate,toplink)的附加功能。除非确实需要,否则您希望远离这些额外的实现特定库,并且只将它们的实现用于JPA 2.这样,如果您不喜欢一个实现,例如hibernate,您可以将其切换为另一个例如。 TopLink的。

要确保您仅使用JPA 2 Spec实现,请仅使用javax.persistence个包中的类,并远离org.hibernate

一旦定义了对象类并使用注释将其映射到数据库,就需要使用名为persistence.xml的文件(需要位于项目类路径中)来配置JPA。这个文件主要做两件事:1。定义一个持久性单元(映射到表的对象列表)和2.配置属性(可以包括数据库连接和自动在数据库上创建表)。

这是一个很好的例子:Hibernate: Automatically creating/updating the db tables based on entity classes