JPA - 在非实体类中联接两个表

2022-09-02 19:15:20

我是一个新手,试图谷歌,但我无法解决我的查询。请帮忙。

我正在尝试映射两个实体:PersonA 和 Person 在我的 POJO 类 PersonC 中

@Entity
class PersonA{
     String sample_field;
}

@Entity
class Person{
     String id;
     String name;

}

以上两个是 jpa 的实体。

现在我想将它们合并为一个 pojo 类。

class PersonC
{
   Strind id;
   String address;
}

尝试了下面的代码,但当我尝试获取地址/外键字段时,它不起作用。

@SqlResultSetMapping(name="PersonC", 
classes = {
   @ConstructorResult(targetClass = PersonC.class, 
    columns = {@ColumnResult(name="name")
              , @ColumnResult(name="address")
    )}

我应该在哪里定义@SqlResultSetMapping,上面的哪个类?) })


答案 1

@SqlResultSetMapping可以放置在任何实体类中(不要注释POJO - 它不起作用)。在 JPA 的 2.1 版中添加了到 POJO 类的映射。与映射一起使用的 POJO 必须具有正确的构造函数。@ConstructorResult

与预期构造函数的参数对应的所有列都必须使用构造函数Result批注的 columns 元素以与构造函数的参数列表相同的顺序指定。

请查阅以下示例中的查询用法,并相应地计算您的情况。

@Entity
public class Address {
    @Id int id;  
    String street;
}


@SqlResultSetMapping(name="PersonDTOMapping",
    classes = {
     @ConstructorResult(targetClass = PersonDTO.class,
       columns = {@ColumnResult(name="name"), @ColumnResult(name="street")}
     )}
)
@Entity
public class Person {
    @Id int id;
    String name;
    Address address;  
}  

public class PersonDTO {
    String name;
    String street;
    public PersonDTO(String name, String street) {
        this.name = name;
        this.street = street;
    }
}

// usage
Query query = em.createNativeQuery(
    "SELECT p.name AS name, a.street AS street FROM Person p, Address a WHERE p.address_id=a.id",
    "PersonDTOMapping");
List<PersonDTO> result = query.getResultList();

请注意,别名 ( 和 ) 必须与 s 中的名称匹配。该示例针对 Ecliselink 2.5.1 进行了测试。AS nameAS street@ColumnResult


答案 2

只是使用JPQL找到了一个更简单的解决方案。我从@zbig的答案中窃取了部分示例:

@Entity
public class Address {
    @Id int id;  
    String street;
}

@Entity
public class Person {
    @Id int id;
    String name;
    Address address;  
}  

public class PersonDTO {
    String name;
    String street;
    public PersonDTO(String name, String street) {
        this.name = name;
        this.street = street;
    }
}

List<PersonDTO> listOfPersons = em.createQuery("select new com.example.PersonDTO(p.name, a.street) " +
"from Person p, Address a " + 
"WHERE p.address.id=a.id", PersonDTO.class).getResultList();

此解决方案的好处是,您不需要使用@SqlResultSetMapping注释,它必须放置在任何实体类上,而不是 DTO 类上!这有时会令人困惑,因为实体类只能部分相关(例如,在联接多个表时)。

更多信息请点击这里


推荐