获取ManyToMany映射表的ID [英] Get id's of a ManyToMany mapping table

查看:117
本文介绍了获取ManyToMany映射表的ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Spring Boot和Hibernate编写一个API,其中我的持久实体对象也用作发送到客户端和从客户端发送的DTO。这是我使用的典型实体的简化版本:

  @Entity 
@Table(name =STUDENT )
public class Student {
@Id
@GeneratedValue
@Column(name =ID)
private Long id;

@ElementCollection
@CollectionTable(name =GROUP_STUDENT,
joinColumns = @JoinColumn(name =GROUP_ID))
@Column(name =STUDENT_ID )
private Set< Long>组id;
$ b $ @ @JsonIgnore
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name =GROUP_STUDENT,
joinColumns = @JoinColumn(name =GROUP_ID ),
inverseJoinColumns = @JoinColumn(name =STUDENT_ID)

private Set< Group> groups = new HashSet<>();

// getters and setters
}

这是相关的类:

  @Entity 
@Table(name =GROUP)
public class Group {
@Id
@GeneratedValue
@Column(name =ID)
private Long id;

@JsonIgnore
@ManyToMany(fetch = FetchType.LAZY,mappedBy =groups)
private设置< Student> students = new HashSet<>();

// getters and setters
}

尽可以请参阅 Student 组之间的 @ManyToMany 关联>。



由于我将这些对象发送给客户端,因此我只选择发送关联的id,而不发送关联本身。我已经解决了这个问题,使用这个答案,并按预期工作。



问题是这样的。当hibernate尝试保存一个 Student 对象时,它会按照预期插入 groups ,但它也会尝试插入 groupIds 放入映射表 GROUP_STUDENT 中。这当然会失败,因为映射表组合标识的唯一约束。而且 groupIds 不能标记为 insertable = false ,因为它是 @ElementCollection 。我不认为我可以使用 @Formula ,因为我需要一个 Set 而不是减少的值。



当然可以通过清空 groupIds groups c $ c>在保存或保留这样一个实体之前,但这是非常危险和容易忘记。

所以我想要的基本上是一个只读<$ c $在 Student 类中的c> groupIds ,它从 GROUP_STUDENT 映射表中加载数据。这可能吗?我非常感谢任何建议,并且很乐意在这个问题上进行细化,看看是否还不清楚。

解决方案

我已经设法解决这通过使id集合 @Transient 并使用 @PostLoad 来填充它:

  @Entity 
@Table(name =STUDENT)
public class Student {
@PostLoad
private void postLoad(){
groupIds = groups.stream()。map(Group :: getId).collect(Collectors.toSet());
}

@Id
@GeneratedValue
@Column(name =ID)
私人长ID;

@Transient
private Set< Long>组id;
$ b $ @ @JsonIgnore
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name =GROUP_STUDENT,
joinColumns = @JoinColumn(name =GROUP_ID ),
inverseJoinColumns = @JoinColumn(name =STUDENT_ID)

private Set< Group> groups = new HashSet<>();

// getters and setters
}


I'm writing an API using Spring Boot and Hibernate where my persisted entity objects are also used as DTOs sent to and from the client. This is a simplified version of a typical entity I use:

@Entity
@Table(name = "STUDENT")
public class Student {
    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @ElementCollection
    @CollectionTable(name = "GROUP_STUDENT",
                     joinColumns = @JoinColumn(name = "GROUP_ID"))
    @Column(name="STUDENT_ID")
    private Set<Long> groupIds;

    @JsonIgnore
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name="GROUP_STUDENT",
               joinColumns = @JoinColumn(name="GROUP_ID"),
               inverseJoinColumns = @JoinColumn(name="STUDENT_ID")
    )
    private Set<Group> groups = new HashSet<>();

    // getters and setters
}

and this is the associated class:

@Entity
@Table(name = "GROUP")
public class Group {
    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @JsonIgnore
    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "groups")
    private Set<Student> students = new HashSet<>();

    // getters and setters
}

As you can see, there is a @ManyToMany association between Student and Group.

Since I send objects like these to the client, I choose to send only the id's of the associations and not the associations themselves. I've solved this using this answer and it works as expected.

The problem is this. When hibernate tries to persist a Student object, it inserts the groups as expected, but it also tries to insert the groupIds into the mapping table GROUP_STUDENT. This will of course fail because of the unique constraint of the mapping table composite id. And it isn't possible to mark the groupIds as insertable = false since it is an @ElementCollection. And I don't think I can use @Formula since I require a Set and not a reduced value.

This can of course be solved by always emptying either the groups of the groupIds before saving or persisting such an entity, but this is extremely risky and easy to forget.

So what I want is basically a read only groupIds in the Student class that loads the data from the GROUP_STUDENT mapping table. Is this possible? I'm grateful for any suggestions and glad to ellaborate on the question if it seems unclear.

解决方案

I've managed to solve this by making the id-collection @Transient and populating it using @PostLoad:

@Entity
@Table(name = "STUDENT")
public class Student {
    @PostLoad
    private void postLoad() {
        groupIds = groups.stream().map(Group::getId).collect(Collectors.toSet());
    }

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @Transient
    private Set<Long> groupIds;

    @JsonIgnore
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name="GROUP_STUDENT",
               joinColumns = @JoinColumn(name="GROUP_ID"),
               inverseJoinColumns = @JoinColumn(name="STUDENT_ID")
    )
    private Set<Group> groups = new HashSet<>();

    // getters and setters
}

这篇关于获取ManyToMany映射表的ID的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆