由于我最近遇到了这个问题并且仍然很挣扎,所以我想分享一个complete code example。此示例使用单独的@EmbeddedId 类,它仍将创建一个包含 3 个 PK/FK 列的表。我的示例使用 Lombok 来填充一堆样板代码,例如 getter/setter、构造函数等。还需要覆盖 equals 和 hashcode 方法。这是使用 Spring 框架编写的,该框架连接了 repos 和测试。希望有人发现这是一个有用的指南。
/* ENTITY CLASSES */
@Entity
@Data
@Table(name = "_Who")
public class Who {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "who", fetch = FetchType.EAGER)
@JsonManagedReference
List<WhoWhatWhere> storage;
}
@Entity
@Data
@Table(name = "_What")
public class What {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String thing;
}
@Entity
@Data
@Table(name = "_Where")
public class Where {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String place;
}
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Entity
@NoArgsConstructor
@Table(name = "_WhoWhatWhere")
public class WhoWhatWhere {
public WhoWhatWhere(Who who, What what, Where where) {
this.who = who;
this.what = what;
this.where = where;
this.setId(new WhoWhatWhereId(who.getId(), what.getId(), where.getId()));
}
@EmbeddedId
WhoWhatWhereId id;
@ManyToOne(fetch = FetchType.EAGER)
@JsonBackReference
@JoinColumn(name = "who_id", insertable = false, updatable = false)
private Who who;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "what_id", insertable = false, updatable = false)
private What what;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "where_id", insertable = false, updatable = false)
private Where where;
}
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class WhoWhatWhereId implements Serializable {
@Column(name = "who_id")
Long whoId;
@Column(name = "what_id")
Long whatId;
@Column(name = "where_id")
Long whereId;
}
/* REPOSITORIES */
@Repository
public interface WhoRepository extends PagingAndSortingRepository<Who, Long> {
Iterable<Who> findWhoByName (String name);
}
@Repository
public interface WhatRepository extends PagingAndSortingRepository<What, Long> {
}
@Repository
public interface WhereRepository extends PagingAndSortingRepository<Where, Long> {
}
@Repository
public interface WhoWhatWhereRepository extends PagingAndSortingRepository<WhoWhatWhere, WhoWhatWhereId> {
}
/* TEST CLASS */
@SpringBootTest
@Slf4j
public class ThreeWayAssocTest {
private final WhoRepository whoRepository;
private final WhatRepository whatRepository;
private final WhereRepository whereRepository;
private final WhoWhatWhereRepository whoWhatWhereRepository;
@Autowired
public ThreeWayAssocTest(WhoRepository whoRepository, WhatRepository whatRepository, WhereRepository whereRepository, WhoWhatWhereRepository whoWhatWhereRepository) {
this.whoRepository = whoRepository;
this.whatRepository = whatRepository;
this.whereRepository = whereRepository;
this.whoWhatWhereRepository = whoWhatWhereRepository;
}
@Test
public void attemptPersistence() {
/*
* the commented pieces can be used to do the initial inserts. Later, fetch existing values so as not to fill
* up the database
*/
Who who =
/* new Who();
who.setName("Carl");
whoRepository.save(who);*/
whoRepository.findById(1L).get();
What what =
/* new What();
what.setThing("strawberry");
whatRepository.save(what);
what.setThing("salad");
whatRepository.save(what);*/
whatRepository.findById(2L).get();
Where where =
/* new Where();
where.setPlace("plate");
whereRepository.save(where);*/
whereRepository.findById(1L).get();
WhoWhatWhere whoWhatWhere = new WhoWhatWhere(who, what, where);
whoWhatWhereRepository.save(whoWhatWhere);
LOGGER.debug("finished");
}
@Test
public void testSerializing() throws JsonProcessingException {
Iterable<Who> examples = whoRepository.findWhoByName("Carl");
Who carl = examples.iterator().next();
LOGGER.debug("Carl: {}", carl);
LOGGER.debug("found some: \n {}", new ObjectMapper().writeValueAsString(examples));
}
}