【问题标题】:How to avoid string members in hibernate?如何避免休眠中的字符串成员?
【发布时间】:2016-08-07 04:43:18
【问题描述】:

是否可以避免在 Hibernate 中使用字符串字面量,例如在标准限制和投影中:

Criteria criteria = session.createCriteria(Employee.class)
                   .add(Restrictions.eq("name", "john doe"));

Projection p1 = Projection.property("name");

例如在上面的代码sn-ps中,将"name"替换为something.name ,其中something 包含 Employee 类的所有成员。

它会减少出错的可能性,例如字符串中的拼写错误。

编辑:将问题更新为更笼统,而不是仅针对标准。

【问题讨论】:

  • 您是否尝试将"name" 替换为"something.name"?如果是,您是否收到错误或什么?
  • 但我的问题是我不知道something应该是什么?
  • 请检查我的回答,它应该对你有帮助。
  • 看看 Yuri answerjooq

标签: java hibernate jakarta-ee hibernate-criteria


【解决方案1】:

您可以使用 Criteria API 打开 JPA 的元模型生成并将生成的类的字段用作类型和名称安全的“文字”。 来自Hibernate docs的示例

@Entity
public class Order {
    @Id
    @GeneratedValue
    Integer id;

    @ManyToOne
    Customer customer;

    @OneToMany
    Set<Item> items;
    BigDecimal totalCost;
    // standard setter/getter methods
}

@StaticMetamodel(Order.class) // <<<<<<<<<< this class gets generated for you
public class Order_ {
    public static volatile SingularAttribute<Order, Integer> id;
    public static volatile SingularAttribute<Order, Customer> customer;
    public static volatile SetAttribute<Order, Item> items;
    public static volatile SingularAttribute<Order, BigDecimal> totalCost;
}
// type-safe and typo-proof building of query:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
SetJoin<Order, Item> itemNode = cq.from(Order.class).join(Order_.items);
cq.where( cb.equal(itemNode.get(Item_.id), 5 ) ).distinct(true);

在大型实体和复杂查询的情况下非常方便。唯一的缺点是有时它会变得非常冗长。
它是 JPA 标准,因此 EclipseLink 和其他 JPA 提供商也支持它。

【讨论】:

    【解决方案2】:

    您可以创建一个员工常量类:

    public class EmployeeConstants {
            public static final String firstName= "firstname";
            public static final String lastName= "lastname";
            ....
    }
    

    并将该字段称为:

    Criteria criteria = session.createCriteria(Employee.class)
                       .add(Restrictions.eq(EmployeeConstants.firstName, "john doe"));
    

    实际上EmployeeConstants.firstNamereturns firstname 必须是Employee 实体的字段名称。

    【讨论】:

    • 我已经考虑过了,但这更像是一种解决方法而不是解决方案。它肯定比在 Hibernate 代码中使用字符串文字要好,但不如 linq 语法那么优雅,因为它在对基进行更改时更新 Contants 类有额外的开销。如果 Hibernate 本身不支持这似乎是最好的方法。
    • @JohnSteed :是的,正如您所说,这比在休眠代码中使用字符串文字更好,看来我们没有更好的解决方案。
    • 但是有一个更好的解决方案,实际上不止一个。
    【解决方案3】:

    在您的情况下,您可以通过示例使用查询:

    Employee employee = new Employee();
    employee.setName("john doe");
    Example employeeExample = Example.create(employee);
    
    Criteria criteria = session.createCriteria(Employee.class).add(employeeExample);
    

    【讨论】:

    • 感谢您的回复。对不起,我的问题太具体了。我的意思是在使用 Hibrenate 的过程中避免使用字符串来指定成员。我已经更新了我原来的问题
    猜你喜欢
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-03-31
    • 1970-01-01
    • 2011-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多