【问题标题】:Hibernate joining 2 rows休眠加入2行
【发布时间】:2013-03-01 15:03:00
【问题描述】:

为了使我的 java 代码更简单,我想将两行合并为一,因为我确实需要这两行才能使用数据。

假设这些是我表的字段:

ID, FIELD1, FIELD2, DISCRIMINATOR, VALUE

显然,ID 是主键。 FIELD1 和 2 让我们识别一个由 2 行组成的“组”,它们的区别仅在于 DISCRIMINATOR 和 VALUE(鉴别器指示值代表什么)

我希望每个“组”有一个 POJO(其中 FIELD1 和 2 将用作复合 ID),例如:

FIELD1, FIELD2, VALUE1, VALUE2

地点:

VALUE1 = 鉴别器 A 的 VALUE

VALUE2 = 鉴别器 B 的值

在 SQL 中,我会这样请求:

SELECT a.FIELD1, a.FIELD2, a.VALUE as VALUE1, b.VALUE as VALUE2
FROM TABLE a, TABLE b
WHERE a.FIELD1 = b.FIELD1 and a.FIELD2 = b.FIELD2
  AND a.DISCRIMINATOR = 'A'
  AND b.DISCRIMINATOR = 'B'

不幸的是,我不知道如何让它进入休眠状态,我现在对所有可能性感到困惑。

我宁愿将解决方案作为映射的 XML,但如果别无选择,我仍然会采用注释解决方案。

【问题讨论】:

  • 您在考虑表格。 Hibernate 是一种 ORM 解决方案,可让您假装对象是宇宙的中心。您应该考虑对象或放弃 Hibernate 以获得基于 SQL 的解决方案,例如 Spring JdbcTemplate 或 iBatis。
  • 谢谢,不幸的是,应用程序已经使用休眠进行了很多处理,我无法控制为 db 和 api 所做的选择。不过,我会在以后的作品中记住这一点。
  • 它不必是全有或全无的解决方案。您不必强迫 Hibernate 完成这一切。为什么直接 SQL 不能在这里工作?
  • 我误解了你的评论,我想我会尝试使用它,因为应用程序已经在使用 spring 框架。谢谢
  • 这对我来说听起来更好——SimpleJdbcTemplate 和映射就可以正常工作。让 Spring 来做吧。

标签: hibernate join self discriminator composite-id


【解决方案1】:

如果您非常简单地将表映射到 POJO(这里使用注释,但您可以使用 XML):

@Entity
@Table(name = "whatever")
public class Fields {

    @Id
    @Column(name = "ID")
    private String id;

    @Column(name = "FIELD1")
    private String field1;

    @Column(name = "FIELD2")
    private String field2;

    @Column(name = "DISCRIMINATOR")
    private String discriminator;

    @Column(name = "VALUE")
    private String value;
}

您可以定义一个包含字段和值的单独 POJO:

public class FieldValues {
    private String field1, field2, value1, value2;

    public FieldValues( String field1, String field2, String value1, String value2 ) {
        this.field1 = field1;
        this.field2 = field2;
        this.value1 = value1;
        this.value2 = value2;
    }
}

然后您可以使用 JPQL 准确编写您列出的查询,在 EntityManager 中执行它,它仍然会参与所有 JPA 事务等等。

String sql =   "SELECT a.field1, a.field2, a.value as value1, b.value as value2 "
             + "  FROM Fields a, Fields b "
             + " WHERE a.FIELD1 = b.FIELD1 and a.FIELD2 = b.FIELD2 "
             + "   AND a.DISCRIMINATOR = 'A' "
             + "   AND b.DISCRIMINATOR = 'B'";
List<Object[]> result = entityManager.createQuery(sql, Object[].class);

List<FieldValues> result = new ArrayList<FieldValues>();
for (Object[] fieldSet : result) {
    String field1 = (String) fieldSet[0];
    String field2 = (String) fieldSet[1];
    String value1 = (String) fieldSet[2];
    String value2 = (String) fieldSet[3];
    result.add(new FieldValues(field1, field2, value1, value2));
}

我相信你甚至可以让 Hibernate 为你映射到 FieldValues,但我不记得如何了。这可能就像用正确的列名注释(或 XML 映射)FieldValues 类一样简单,然后强制 Hibernate 从查询中返回 List&lt;FieldValues&gt;。这种方法的缺点是您无法对FieldValue 进行更改并将其保存到数据库中。

另一种方法是使用带有EntityManager.createNativeQuery 的普通旧SQL。您必须确保在执行此操作之前刷新实体管理器;否则任何挂起的更改可能尚未写入数据库,因此您的查询不会看到。同样,我相信在这种情况下,您可以让 Hibernate 映射到 FieldValues 类。

【讨论】:

  • 谢谢。我想我可以使用 SQL 查询,但在这种情况下,休眠映射将失去它的目的(甚至有用于创建字段 POJO)。我开始认为我的表格或我试图实现的目标与 hibernate 的原始目的太远了。
猜你喜欢
  • 2015-04-16
  • 2016-03-15
  • 2013-05-22
  • 2018-07-16
  • 1970-01-01
  • 2014-09-04
  • 2018-02-03
  • 1970-01-01
相关资源
最近更新 更多