Java JPA-在非实体类中连接两个表
我是一个新手,尝试用谷歌搜索,但我无法解决我的问题。 请帮忙 我试图映射两个实体:我的POJO类PersonC中的PersonA和PersonJava JPA-在非实体类中连接两个表,java,mysql,sql,jpa,Java,Mysql,Sql,Jpa,我是一个新手,尝试用谷歌搜索,但我无法解决我的问题。 请帮忙 我试图映射两个实体:我的POJO类PersonC中的PersonA和Person @Entity class PersonA{ String sample_field; } @Entity class Person{ String id; String name; } 以上两个是jpa的实体 现在我想把它们合并到一个pojo类中 class PersonC { Strind id; St
@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,上面的哪个类?
)
})
@SqlResultSetMapping
可以放置在任何实体类中(不要注释POJO-它不会工作)。JPA的2.1版中添加了映射到具有@ConstructorResult
的POJO类。与映射一起使用的POJO必须具有正确的构造函数
必须使用ConstructorResult注释的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();
@实体
公共课堂演讲{
@Id-int-Id;
弦街;;
}
@SQLResultsMapping(name=“PersonDTOMapping”,
类别={
@ConstructorResult(targetClass=PersonDTO.class,
columns={@ColumnResult(name=“name”),@ColumnResult(name=“street”)}
)}
)
@实体
公共阶层人士{
@Id-int-Id;
字符串名;
地址;
}
公共类个人{
字符串名;
弦街;;
公众人物(字符串名称、字符串街道){
this.name=名称;
这条街;
}
}
//用法
Query Query=em.createNativeQuery(
“选择p.name作为姓名,a.street作为个人p的街道,地址a,其中p.Address_id=a.id”,
“个人地图”);
List result=query.getResultList();
请注意,别名(AS name
和AS street
)必须与@ColumnResult
中的名称匹配。
该示例针对Ecliselink 2.5.1进行了测试。刚刚发现了一个使用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();
@实体
公共课堂演讲{
@Id-int-Id;
弦街;;
}
@实体
公共阶层人士{
@Id-int-Id;
字符串名;
地址;
}
公共类个人{
字符串名;
弦街;;
公众人物(字符串名称、字符串街道){
this.name=名称;
这条街;
}
}
List listOfPersons=em.createQuery(“选择new com.example.PersonDTO(p.name,a.street)”+
“来自p人,地址a”+
“其中p.address.id=a.id”,PersonDTO.class).getResultList();
此解决方案的好处是您不需要使用@SqlResultSetMapping注释,必须将@SqlResultSetMapping注释放置在任何实体类上,而不是DTO类上!这有时会让人困惑,因为实体类只能部分相关(例如在连接多个表时)
更多信息这篇文章是关于冬眠的 将@SqlResultSetMapping和@NamedNativeQuery(或@NamedQuery)放在@Entity类定义中的建议并不优雅,显然不遵循关注点分离原则 更合适的解决方案是使用@MappedSuperclass注释,如下所示: SingerExpanded.java(类必须是抽象的): 然后DAO类singerestendedao.java:
package pl.music.model.singer.extended;
import javax.persistence.ColumnResult;
import javax.persistence.ConstructorResult;
import javax.persistence.MappedSuperclass;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.SqlResultSetMapping;
@MappedSuperclass
@SqlResultSetMapping( // @formatter:off
name = "SingerExtendedMapping",
classes = @ConstructorResult(
targetClass = SingerExtendedDTO.class,
columns = {
@ColumnResult(name = "singer_id", type = Long.class),
@ColumnResult(name = "first_name"),
@ColumnResult(name = "last_name"),
@ColumnResult(name = "count_albums", type = Long.class)
}
)
)
@NamedNativeQueries({
@NamedNativeQuery(
name = "SingerExtendedAsc",
query = "select"
+ " singer.singer_id,"
+ " singer.first_name,"
+ " singer.last_name,"
+ " (select count(*) from album where album.singer_id = singer.singer_id) as count_albums"
+ " from singer"
+ " group by singer.singer_id"
+ " order by last_name collate :collation asc, first_name collate :collation asc",
resultSetMapping = "SingerExtendedMapping"
)
}) // @formatter:on
public abstract class SingerExtended {
}
package pl.music.model.singer.extended;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SingerExtendedDAO {
@PersistenceContext
EntityManager entityManager;
@Autowired
private String collation;
public List<SingerExtendedDTO> getAll(Integer page, Integer count) {
TypedQuery<SingerExtendedDTO> query = entityManager.createNamedQuery("SingerExtendedAsc", SingerExtendedDTO.class);
query.setParameter("collation", collation);
if ((count != null) && (count.intValue() > 0)) {
query.setMaxResults(count.intValue());
if ((page != null) && (page.intValue() >= 0)) {
query.setFirstResult(count.intValue() * page.intValue());
}
}
List<SingerExtendedDTO> singerExtendedDTOs = query.getResultList();
return singerExtendedDTOs;
}
}
如果按照上述方式将所有这些放在一起,我们将得到一个合适的解决方案:
- 一切都在一个包裹里
- 查询声明不会污染任何无关实体
- 保持关注点的分离(分离的查询+映射、DAO和DTO)
package pl.music.model.singer.extended;
public class SingerExtendedDTO {
private Long singerId;
private String firstName;
private String lastName;
private Long countAlbums;
// IMPORTANT: this constructor must be defined !!!
public SingerExtendedDTO(Long singerId, String firstName, String lastName, Long countAlbums) {
this.singerId = singerId;
this.firstName = firstName;
this.lastName = lastName;
this.countAlbums = countAlbums;
}
... getters & setters ...
}