当前位置: 首页 > 知识库问答 >
问题:

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

万俟招
2023-03-14

我对SQL并不陌生,但我对Hibernate完全陌生。我预计,给定一个列值,从表中选择一组对象将是一项非常简单的任务。但我做不到。

我的导师和下面的这个问题都建议了同样的事情,这让我写了下面的代码: JPA:如何基于除ID之外的字段值获取实体?

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

这是可行的,但方法是会话。createCriteria()已被弃用。由于我对hibernate还不熟悉,我不妨按照它的预期工作方式来学习它,所以我不想使用不推荐的方法。

官方的Hibernate文档只是说使用JPA标准。我发现了极其冗长的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();

如果这是正确的方法,我认为我的标准准备语句方法没有任何优势。这比我见过的任何东西都更冗长、更复杂。

现在,我试图研究关于如何选择对象列表的具体问题,在5.2中不使用不建议使用的方法,并避免JPA必须滚动才能看到完整的代码,但这是我得到的最接近的:Hibernate 5.2版本-

这让我编写了以下代码:

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

虽然这是工作,而且很简单,它打开了SQL注入,如果我有其他东西比int作为变量值。在代码审查中,我还被告知,当使用Hibernate时,不需要SQL语法。

不用说,我有点沮丧的是,本应如此简单的事情实际上真的很难弄清楚。它要么被弃用,极其冗长,要么容易SQL注射。有人知道我是否错过了一些明显的东西,或者Hibernate在这种情况下只是设计不佳和/或记录不足吗?

共有2个答案

督建柏
2023-03-14

首先,这就是我如何初始化entityManager:调用Persistence.createEntityManagerFactory

这是一个如何选择行的示例:

你有你的实体映射到一个表,例如客户表:

@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等)来实现这一点。JPA2.0规范提供了这方面的规范。这些规范由第三方库实现,例如(Hibernate、TopLink等)。有时,这些库为您提供了与顶级JPA 2.0规范上的实现(hibernate、toplink)特定的附加功能。除非确实需要,否则您希望远离这些附加的特定于实现的库,只将它们的实现用于JPA 2。这样,如果你不喜欢一个实现,比如hibernate,你可以把它换成另一个,比如TopLink。

为了确保只使用JPA2规范实现,只使用javax中的类。持久性打包,远离组织。Hibernate

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

这是一个很好的例子:Hibernate:基于实体类自动创建/更新db表

唐焕
2023-03-14

虽然这是可行的,而且很简单,但如果我将int以外的东西作为变量值,它就为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版本)。

这是文件。

顺便说一句,您应该考虑使用标准的JPA API,而不是专有的Hibernate API。

 类似资料:
  • 问题内容: 说有这样的表: 字段名称很容易解释。我想选择同时具有1和3 的,因此在此示例中仅。我想到了类似的 清单,之后我想列出该组中存在的。我怎么做? 问题答案: 如果没有任何唯一约束,请尝试: 如果仅尝试检测两个值,请使用此子句: 如果post_id和tag_id都具有唯一约束,那么这也应该起作用:

  • 我有一个mySQL查询,它将选择一些饮料并返回关于饮料的基本信息,以及该特定饮料的成分列表,以及该特定饮料的评级。我有三桌酒水,drinks_ratings,drinks_ing 所以,我的问题是,如果我想获得关于含有伏特加的饮料的信息,并且是在高球玻璃杯中,我会运行下面的查询... 它起作用了,只是我的问题是它没有返回所有的成分。例如,如果我返回“randomdrinkname1”,它碰巧有伏特

  • 我有一个带有数组列的数据帧: 我读了这个CSV,并将“类”列的值转换成数组: 现在我想选择“类”值中具有“performer_0”的行。像这样: 但是这个代码不起作用: 回溯(最后一次调用):文件“d:\pyenv\pandas\lib\site packages\pandas\core\indexes\base.py”,第2657行,在get_loc return self.\u engine.

  • 对于上下文,我的最终目标是从非常大的数据帧中删除几乎重复的行。以下是一些虚拟数据: 在此数据中,来自unique_1和unique_2的观测值的组合应该是不同的,但它们并非总是如此。当它们重复时,它们对于绝大多数列具有相同的值,但在非常小的其他列集上具有变化。我正在尝试制定一种策略来处理近似重复项,但这很复杂,因为每组近似重复项都有一组不同的列,其中包含变化。 我正在尝试一次查看包含一组近似重复项

  • 问题内容: 我的表是: 我想列出一组具有相同疾病的患者。pid和did分别是患者和疾病表中的主键,并且是has_disease表中的外键。 样本数据: 耐心 疾病 has_disease 以上数据的答案是因为它们具有完全相同的疾病1和3,即疟疾和病毒热。我想知道如何在mysql中实现这一点。 。 问题答案: 该查询返回给我们患者及其疾病。 通过完整的剂量列表比较2组患者,并将pid保留为相同的剂量

  • 问题内容: 我想选择不具有VAL =’current’的任何行的唯一ID(与多行关联)。 例如,在这样的表中: 我希望它返回ID 23,因为它没有VAL =’current’的行。请注意,在此表中,主键(PK)是唯一的,但ID不是唯一的(因此需要使用DISTINCT或GROUP BY)。 这是我在PHP中拥有的东西: 这就是它的总要旨。如您所见,完成此任务需要两个SQL语句。有没有更短的方法可以做