从一个视图映射具有嵌入式列表的实体
Map the entity with embedded List from one view
我正在尝试使用 spring-data-jpa 实现简单的 cqrs 应用程序
所以我有 2 个表用来写 - 例如人和汽车(一个人可以有汽车清单)。
我还使用创建为 select * 来自 person join car...
的一个视图
所以来自的示例查询可以给出输出(一个用户有 2 辆车)
firstName|lastName| car_brand | car_model |
marek |k | tesla | s |
marek |k | mercdes | 190 |
现在我正在尝试在 jpa 中映射此视图,并且正在尝试嵌入列表
@Embeddable
class CarSnapshot {
private String carBrand;
private String carModel;
}
和
class PersonSnapshot {
private String firstName;
@Embedded // I tried also @OneToMany and ElementCollection
private Set<CarSnapshot> cars;
}
但这对我来说不起作用。你知道如何解决吗
此外,一对一映射(一个人最多拥有一辆汽车)效果非常好
如果你想使用可嵌入类型,你可以执行以下操作:
@Entity
@Table(name = "persons")
public class Person {
@Id
private Integer id;
@ElementCollection
@CollectionTable(name = "person_cars", joinColumns = @JoinColumn(name = "person_id"), foreignKey = @ForeignKey(name = "person_cars_persons_fk"))
private List<PersonCar> cars;
}
@Embeddable
class PersonCar {
@Column(length = 32, nullable = false)
private String brand;
@Column(length = 32, nullable = false)
private String model;
}
在这种情况下,您的数据库架构可以是这样的:
create table persons (
id integer not null constraint persons_pkey primary key,
);
create table person_cars (
person_id integer not null constraint person_cars_persons_fk references persons,
brand varchar(32) not null,
model varchar(32) not null,
constraint supported_docs_pkey primary key (doc_type, country_code)
);
(这是 postgresql 方言)
更多信息在这里:Hibernate User Guide - Collections of value types
已更新
要将视图映射到实体,您可以这样做:
@Data // It's Lombok annotation - c-tor, getters/setters etc.
@Entity
@Immutable
@IdClass(View.class)
@Subselect("select p.name as person_name, c.brand as car_brand, c.model as car_model from persons p join cars c on p.id = c.person_id")
public class View implements Serializable {
@Id private String personName;
@Id private String carBrand;
@Id private String carModel;
}
您可以使用带有视图名称的 @Table
注释,而不是使用 @Subselect
注释:
@Data
@Entity
@Immutable
@IdClass(View.class)
@Table(name = "my_view")
public class View implements Serializable {...}
工作demo。
已更新 2
解决方法 post-processing...
DTO:
@Value
public class PersonDto {
private String name;
private List<CarDto> cars = new ArrayList<>();
public PersonDto addCars(List<CarDto> cars) {
this.cars.addAll(cars);
return this;
}
}
@Value
public class CarDto {
private String brand;
private String model;
}
和ViewRepo
public interface ViewRepo extends JpaRepository<View, View> {
List<View> findByPersonName(String name);
default PersonDto getPersonByName(String personName) {
return new PersonDto(personName)
.addCars(findByPersonName(personName)
.stream()
.map(p -> new CarDto(p.getCarBrand(), p.getCarModel()))
.collect(Collectors.toList()));
}
}
我正在尝试使用 spring-data-jpa 实现简单的 cqrs 应用程序 所以我有 2 个表用来写 - 例如人和汽车(一个人可以有汽车清单)。 我还使用创建为 select * 来自 person join car...
的一个视图所以来自的示例查询可以给出输出(一个用户有 2 辆车)
firstName|lastName| car_brand | car_model |
marek |k | tesla | s |
marek |k | mercdes | 190 |
现在我正在尝试在 jpa 中映射此视图,并且正在尝试嵌入列表
@Embeddable
class CarSnapshot {
private String carBrand;
private String carModel;
}
和
class PersonSnapshot {
private String firstName;
@Embedded // I tried also @OneToMany and ElementCollection
private Set<CarSnapshot> cars;
}
但这对我来说不起作用。你知道如何解决吗 此外,一对一映射(一个人最多拥有一辆汽车)效果非常好
如果你想使用可嵌入类型,你可以执行以下操作:
@Entity
@Table(name = "persons")
public class Person {
@Id
private Integer id;
@ElementCollection
@CollectionTable(name = "person_cars", joinColumns = @JoinColumn(name = "person_id"), foreignKey = @ForeignKey(name = "person_cars_persons_fk"))
private List<PersonCar> cars;
}
@Embeddable
class PersonCar {
@Column(length = 32, nullable = false)
private String brand;
@Column(length = 32, nullable = false)
private String model;
}
在这种情况下,您的数据库架构可以是这样的:
create table persons (
id integer not null constraint persons_pkey primary key,
);
create table person_cars (
person_id integer not null constraint person_cars_persons_fk references persons,
brand varchar(32) not null,
model varchar(32) not null,
constraint supported_docs_pkey primary key (doc_type, country_code)
);
(这是 postgresql 方言)
更多信息在这里:Hibernate User Guide - Collections of value types
已更新
要将视图映射到实体,您可以这样做:
@Data // It's Lombok annotation - c-tor, getters/setters etc.
@Entity
@Immutable
@IdClass(View.class)
@Subselect("select p.name as person_name, c.brand as car_brand, c.model as car_model from persons p join cars c on p.id = c.person_id")
public class View implements Serializable {
@Id private String personName;
@Id private String carBrand;
@Id private String carModel;
}
您可以使用带有视图名称的 @Table
注释,而不是使用 @Subselect
注释:
@Data
@Entity
@Immutable
@IdClass(View.class)
@Table(name = "my_view")
public class View implements Serializable {...}
工作demo。
已更新 2
解决方法 post-processing...
DTO:
@Value
public class PersonDto {
private String name;
private List<CarDto> cars = new ArrayList<>();
public PersonDto addCars(List<CarDto> cars) {
this.cars.addAll(cars);
return this;
}
}
@Value
public class CarDto {
private String brand;
private String model;
}
和ViewRepo
public interface ViewRepo extends JpaRepository<View, View> {
List<View> findByPersonName(String name);
default PersonDto getPersonByName(String personName) {
return new PersonDto(personName)
.addCars(findByPersonName(personName)
.stream()
.map(p -> new CarDto(p.getCarBrand(), p.getCarModel()))
.collect(Collectors.toList()));
}
}