起初我以为this solution可能会解决我的问题:
@Entity
public class User {
@JoinTable(name = "user_permission",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "permission_id"))
@MapKeyJoinColumn(name = "project_id")
@ElementCollection
private Map<Project, Permission> permissions = new HashMap<>();
}
@Entity
public class Project {
...
}
@Entity
public class Permission {
...
}
但在此实施中,每Permission
只能设置一个Project
。我希望能够为项目设置多个权限,以便以下内容成立:
| user_id | project_id | permission_id |
|---------|------------|---------------|
| 1 | 1 | 1 |
|---------|------------|---------------|
| 1 | 1 | 2 |
|---------|------------|---------------|
| 1 | 2 | 1 |
|---------|------------|---------------|
| 1 | 2 | 2 |
|---------|------------|---------------|
| 2 | 1 | 1 |
|---------|------------|---------------|
| 2 | 1 | 2 |
|---------|------------|---------------|
| 2 | 2 | 1 |
|---------|------------|---------------|
| 2 | 2 | 2 |
答案 0 :(得分:4)
您可以使用专用于关系表的实体。这就是我们用自己的属性声明关系的方式 这将导致以下实现:
@Entity
@IdClass(PermissionAssignation.class)
public class PermissionAssignation {
@Id
@ManyToOne
@JoinColumn(name="user_id")
private User user;
@Id
@ManyToOne
@JoinColumn(name="project_id")
private Project project;
@Id
@ManyToOne
@JoinColumn(name="permission_id")
private Permission permission;
...
}
我使用了这篇文章中的解决方案:Hibernate and no PK
它解释了如何用字段创建PK(我没有测试它)。
如果它不起作用,您最好使用EmbeddedId
类。
如果您希望您的关系是双向的,那么您可以根据自己的喜好/需要使用Set<PermissionAssignation>
(或List
):
@Entity
public class User {
@OneToMany(mappedBy="user")
private Set<PermissionAssignation> permissions;
}
答案 1 :(得分:0)
因为我最近遇到了这个问题并且还在挣扎,所以我想分享一个 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));
}
}