简体   繁体   English

为JPA本机查询的结果分配ID的最简单方法是什么?

[英]What is the simplest way to assign an ID to a result from a JPA native query?

I have a complex SQL query that I'm implementing as a native query in JPA. 我有一个复杂的SQL查询,正在JPA中作为本机查询实现。 The entity manager is automatically converting each row of my result set into a Person object, resulting in List<Person> 实体管理器会自动将结果集的每一行转换为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;

The entityManager demands that the Student bean is annotated with @Entity , and this requires an @Id . entityManager要求使用@Entity注释Student bean,这需要@Id The API also requires that all fields are matched. API还要求所有字段都匹配。 Unfortunately, my select clause pulls from various sources, so there isn't really an Id. 不幸的是,我的select子句来自各种来源,因此实际上并没有一个ID。 In fact, I'd like to later have an id generated when I call StudentRepostiory.save(student) . 实际上,我稍后希望在调用StudentRepostiory.save(student)时生成一个ID。

I'm in a catch 22 situation. 我处于22状态。 I need an id for the object to be generated, but I don't have an id as yet. 我需要一个ID来生成对象,但是我还没有一个ID。

What should I do? 我该怎么办?

  • I've tried making the ID null. 我尝试将ID设置为null。 It makes all results null. 它使所有结果为空。
  • I've tried making the ID zero. 我尝试将ID设置为零。 It makes all results the same. 它使所有结果相同。
  • I've tried adding a Generation Strategy annotation. 我尝试添加世代策略注释。 Didn't do anything. 什么也没做

For your reference 供你参考

Student.java 学生.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

}

You can use @SqlResultSetMapping and @ConstructorResult to map the results of your native sql query to a POJO/bean, without requiring it to have an id. 您可以使用@SqlResultSetMapping@ConstructorResult映射你的原生SQL查询到一个POJO / bean的结果,而不需要它有一个ID。

Note: @ConstructorResult is only available in JPA 2.1. 注意:@ConstructorResult仅在JPA 2.1中可用。

First, you need to have a constructor in your Student entity that takes 3 parameters: name , dateOfBirth and address . 首先,您需要在Student实体中有一个构造函数,该构造函数采用3个参数: namedateOfBirthaddress Since this is an entity, it requires you to have a default no-arg constructor, so you need to declare that too. 由于这是一个实体,因此需要您具有默认的no-arg构造函数,因此也需要声明它。 So you have 2 constructors, one no-arg and another with 3 args. 因此,您有2个构造函数,一个没有参数,而另一个带有3个参数。

Now you declare your SqlResultSetMapping using @ConstructorResult: 现在,使用@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
}

Now when you call the createNativeQuery , you can pass your SQL string together with the name of the mapping you declared. 现在,当您调用createNativeQuery ,可以将SQL字符串与声明的映射的名称一起传递。

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

Then, later on you can iterate the Student objects in your list and persist them. 然后,稍后您可以遍历列表中的Student对象并保留它们。 Since Student is an entity and objects in your list does not have a value for the id field yet, calling persist on these objects will work. 由于Student是一个实体,并且列表中的对象尚无id字段的值,因此可以在这些对象上调用persist。

You'll see a sample of this implementation in my github repo . 您将在我的github repo中看到此实现的示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM