我正在开发一个数据库,用于添加乐队、音乐家、乐器等。
我有一张桌子“乐队”和一张桌子“音乐家”。他们有一个ManyToMany关系(一个乐队可以有多个音乐家,一个音乐家可以在多个乐队中),有一个额外的桌子BandMusician,有一个embeddedId BandMusicianId。我这样做是因为我希望乐队和音乐家之间的关系也有其他信息,比如音乐家加入乐队的那一年。
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Band {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String genre;
private int year;
@OneToOne(mappedBy = "band")
private Website website;
@OneToMany(mappedBy = "band")
private List<Album> albuns;
@OneToMany(mappedBy = "band")
private List<BandMusician> musicians;
}
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonDeserialize(using = MusicianJsonDeserializer.class)
public class Musician {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@JsonFormat(pattern = "dd-MM-yyyy")
@JsonProperty("DoB")
@Column(name = "date_of_birth")
private LocalDate DoB;
@ManyToMany
@JoinTable(
name = "musician_instruments",
joinColumns = @JoinColumn(name = "musician_id"),
inverseJoinColumns = @JoinColumn(name = "instrument_id")
)
private List<Instrument> instruments = new ArrayList<>();
@OneToMany(mappedBy = "musician")
private List<BandMusician> bands;
public void addInstrument(Instrument instrument) {
this.instruments.add(instrument);
}
}
@Embeddable
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BandMusiciansId implements Serializable{
private static final long serialVersionUID = 1L;
@Column(name = "band_id")
private Long bandId;
@Column(name = "musician_id")
private Long musicianId;
}
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class BandMusician {
@EmbeddedId
private BandMusiciansId id = new BandMusiciansId();
@ManyToOne
@MapsId("bandId")
@JoinColumn(name = "band_id")
private Band band;
@ManyToOne
@MapsId("musicianId")
@JoinColumn(name = "musician_id")
private Musician musician;
private String role;
private int joined;
}
当我收到"/musician“的帖子请求时,我可以拯救一位音乐家。我使用Jackson来反序列化这样的请求:
{
"name": "John the Ripper",
"DoB": "03-12-1965",
"instruments": "voice, guitar",
"bands": "Band1, Band2"
}
与杰克逊,我可以得到每个乐队,搜索与BandRepository和创建一个BandMusician。
THE PROBLEM:当我收到请求时,为了创建一个BandMusician,我必须创建一个BandMusiciansId,为此我需要bandId和MusicianId。但我现在正在创作音乐家,所以我没有musicianId。它是在我拯救音乐家的时候自动创建的。
MusicianJsonDeserializer类
public class MusicianJsonDeserializer extends JsonDeserializer<Musician>{
private final InstrumentRepository instrumentRepository;
private final BandRepository bandRepository;
@Autowired
public MusicianJsonDeserializer(
InstrumentRepository instrumentRepository,
BandRepository bandRepository
) {
this.instrumentRepository = instrumentRepository;
this.bandRepository = bandRepository;
}
@Override
public Musician deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JacksonException {
ObjectCodec codec = p.getCodec();
JsonNode root = codec.readTree(p);
Musician musician = new Musician();
musician.setName(root.get("name").asText());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
musician.setDoB(LocalDate.parse(root.get("DoB").asText(), formatter));
if (root.get("instruments") != null) {
String instrumentList = root.get("instruments").asText();
String[] instrumentArray = instrumentList.split(", ");
List<Instrument> musicianInstrumentList = new ArrayList<>();
for (String instrument : instrumentArray) {
Instrument instrumentFound =
instrumentRepository.findByName(instrument)
.orElseThrow(RuntimeException::new);
// TODO custom exception
musicianInstrumentList.add(instrumentFound);
}
musician.setInstruments(musicianInstrumentList);
}
if (root.get("bands") != null) {
// TODO Stuck here!
我想做的是:在我的MusicianService中,在拯救音乐家之后,我可以创建BandMusician和关系。不过,我认为在服务层中这样做是一个错误的选择。
编辑:为了更容易理解,我创建了一个只有其中相关部分的项目,并将其推送到github (https://github.com/ricardorosa-dev/gettinghelp)。同样,我想要的是能够向"/musician“发送一个帖子,这将被MusicianJsonDeserializer捕获,并为请求体中发送的每个乐队创建一个BandMusicianId和BandMusician。
发布于 2021-12-04 07:10:03
我有实体、乐队和音乐家,他们之间有一个ManyToMany关系,有一个关联表BandMusician。
我想要的是在同一个请求中创建实体音乐家和关系(BandMusician)。
就我所能收集到的信息而言,这是不可能的,因为为了在关联表(BandMusician)中创建记录,我必须已经创建了音乐家(我正在此请求中创建)。
我试过每一件事,只是想看看是否有可能,但没能做到。但是,即使这是可能的,这也是一个非常糟糕的实践,因为它会使类过于紧密耦合。
明确的解决方案是只创建带有此请求的音乐家,然后发送另一个请求来创建Band和音乐家之间的连接。
我还尝试用一个请求在BandMusician表中创建许多条目,这也是不可能的,因为JsonDeserializer表似乎不接受List<>作为返回类型。我试图避免提出很多要求来创建关系条目(例如,对于一个在五个乐队中的音乐家来说),但似乎最好保持清晰和简单。
我现在为每个请求保存一个音乐家乐队的关系:
{
"musician": "Awesome musician",
"band": "Awesome band",
"role": "guitar",
"joined": 2003
}
https://stackoverflow.com/questions/70191536
复制相似问题