java - 将 ID 分配给 JPA native 查询结果的最简单方法是什么?

标签 java sql hibernate jpa hibernate-native-query

我有一个复杂的 SQL 查询,我将其作为 JPA 中的 native 查询实现。实体管理器会自动将结果集的每一行转换为 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 要求 Student bean 注释为 @Entity ,这需要 @Id 。 API 还要求所有字段都匹配。不幸的是,我的 select 子句从各种来源获取,因此没有真正的 Id。事实上,我想稍后在调用 StudentRepostiory.save(student) 时生成一个 id .

我正处于第 22 条军规的境地。我需要一个 id 来生成对象,但我还没有 id。

我应该做什么?

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

供您引用

Student.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

}

最佳答案

您可以使用@SqlResultSetMapping@ConstructorResult将 native 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 对象并保留它们。由于 Student 是一个实体,并且列表中的对象还没有 id 字段的值,因此对这些对象调用 persist 将会起作用。

您将在我的 github repo 中看到此实现的示例.

关于java - 将 ID 分配给 JPA native 查询结果的最简单方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33242496/

相关文章:

java - 如何在不使用 System.setProperty() 的情况下设置 keystore 和信任库

java - 将excel文件发送到spring MVC

从服务器接收数据时 FileOutputStream 出现 java.lang.ArrayIndexOutOfBoundsException

java - 如何将当前时间存储到外部存储器?

mysql - 在 MySQL 选择查询中有条件地设置列的值

java - ConstraintViolationException,我应该期望它被抛出然后处理它吗?或者我应该阻止它被抛出?

PHP echo 不显示在 HTML <h3> 标签内

Mysql JOIN 获取指定列数据语法错误

java - 使用 Hibernate 和 Spring Data JPA 激活 SQL 语句日志记录

java - org.hibernate.id.SequenceHiLoGenerator 给出了错误的 id