有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我有一个复杂的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要求用@Entity注释Studentbean,这需要一个@Id。API还要求所有字段都匹配。不幸的是,我的select子句来自不同的来源,因此实际上没有Id。事实上,我希望稍后在调用StudentRepostiory.save(student)时生成一个Id

我正处于第22条军规的境地。我需要生成对象的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

}

共 (1) 个答案

  1. # 1 楼答案

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

    注意:@ConstructorResult仅在JPA 2.1中提供

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

    现在使用@ConstructorResult声明SQLResultMapping:

    @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中看到这个实现的一个示例