0

我有一个复杂的 SQL 查询,我在 JPA 中将其作为本机查询来实现。实体管理器会自动将我的结果集的每一行转换为一个Person对象,从而导致List<Person>

String sql = "select name, address, date_of_birth from ...";
Query q = entityManager.createNativeQuery(sql, Student.class);
List<Student> results = q.getResultList();
return results;

entityManager 要求Studentbean 使用 注释@Entity,这需要@Id. API 还要求所有字段都匹配。不幸的是,我的 select 子句来自各种来源,因此实际上并没有 ID。事实上,我想稍后在我调用StudentRepostiory.save(student).

我处于第 22 条捕获状态。我需要一个 id 来生成对象,但我还没有 id。

我应该怎么办?

  • 我试过让 ID 为空。它使所有结果为空。
  • 我已经尝试将 ID 设为零。它使所有结果都相同。
  • 我尝试添加生成策略注释。什么都没做。

供你参考

学生.java

@Entity // This forces me to have an Id.
class Student {

    @Id Long id  // I'm forced to include this, but my query doesn't have one

    String name;
    String dateOfBirth;
    String address;

    // Getters and Setters

}
4

1 回答 1

2

您可以使用@SqlResultSetMapping并将@ConstructorResult本机 sql 查询的结果映射到 POJO/bean,而无需它具有 id。

注意:@ConstructorResult 仅在 JPA 2.1 中可用。

首先,您需要在您的Student实体中有一个构造函数,它接受 3 个参数namedateOfBirthaddress。由于这是一个实体,它要求你有一个默认的无参数构造函数,所以你也需要声明它。所以你有 2 个构造函数,一个没有参数,另一个有 3 个参数。

现在您使用@ConstructorResult 声明您的SqlResultSetMapping:

@SqlResultSetMapping(name="StudentMapping",
    classes={
        @ConstructorResult(targetClass=Student.class,
            columns={
                @ColumnResult(name="name", type=String.class),
                @ColumnResult(name="address", type=String.class),
                @ColumnResult(name="date_of_birth", type=String.class)
            })
    }
)
@Entity
public class Student {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int id;

    private String String name;
    private String address;
    private String dateOfBirth;

    public Student () {}

    public Student(String name, String address, String dateOfBirth) {
        this.name = name;
        this.address = address;
        this.dateOfBirth = dateOfBirth;
    }

    // Setters and Getters
}

现在,当您调用 时createNativeQuery,您可以将 SQL 字符串与您声明的映射名称一起传递。

String sql = "select name, address, date_of_birth from ...";
Query q = entityManager.createNativeQuery(sql, "StudentMapping");
List results = q.getResultList();

然后,稍后您可以迭代Student列表中的对象并将它们持久化。由于Studentis 是一个实体,并且列表中的对象还没有 id 字段的值,因此对这些对象调用 persist 将起作用。

您将在我的 github 存储库中看到此实现的示例

于 2015-10-20T17:37:01.230 回答