【问题标题】:Spring Data rest how to perform CRUD on @manytomany relation ,composite table with extra columnSpring Data 休息如何在 @manytomany 关系上执行 CRUD,带有额外列的复合表
【发布时间】:2017-08-28 10:46:50
【问题描述】:

我无法在具有额外列的复合表上通过来自 restful 客户端 Postman 的 json POST 执行 CRUD。我正在使用 Spring boot、spring data rest 和 spring JPA。 我在数据库中有 3 个表
-用户
-能力
-user_competency(加入/复合表与额外的列)

这是我的课程

用户

@Entity
@Table(name = "\"user\"", schema = "public")
@JsonIdentityInfo(
          generator = ObjectIdGenerators.IntSequenceGenerator.class, 
          property = "userId")
public class User implements java.io.Serializable {

    private Long userId;

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)

    @Column(name = "user_id", unique = true, nullable = false)
    public Long getUserId() {
        return this.userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    private Set<UserCompetency> userCompetencies = new HashSet<UserCompetency>(0);

        @OneToMany(fetch = FetchType.EAGER,cascade = {CascadeType.ALL}, mappedBy = "user")
    public Set<UserCompetency> getUserCompetencies() {
        return this.userCompetencies;
    }

    public void setUserCompetencies(Set<UserCompetency> userCompetencies) {
        this.userCompetencies = userCompetencies;
    }

}

能力

@Entity
@Table(name = "competency", schema = "public")
@JsonIdentityInfo(
          generator = ObjectIdGenerators.IntSequenceGenerator.class, 
          property = "competencyId")
public class Competency implements java.io.Serializable {


    private Long competencyId;
    private Set<UserCompetency> userCompetencies = new HashSet<UserCompetency>(0);

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)

    @Column(name = "competency_id", unique = true, nullable = false)
    public Long getCompetencyId() {
        return this.competencyId;
    }

    public void setCompetencyId(Long competencyId) {
        this.competencyId = competencyId;
    }

        @OneToMany(fetch = FetchType.LAZY, mappedBy = "competency")
    public Set<UserCompetency> getUserCompetencies() {
        return this.userCompetencies;
    }

    public void setUserCompetencies(Set<UserCompetency> userCompetencies) {
        this.userCompetencies = userCompetencies;
    }
}   

用户能力

@Entity
@Table(name = "user_competency", schema = "public")
@JsonIdentityInfo(
          generator =ObjectIdGenerators.IntSequenceGenerator.class, 
          property = "id")
public class UserCompetency implements java.io.Serializable {
    private UserCompetencyId id;
    private Level level;
    private User user;
    private Competency competency;

    @EmbeddedId

    @AttributeOverrides({
            @AttributeOverride(name = "competencyId", column = @Column(name = "competency_id", nullable = false)),
            @AttributeOverride(name = "userId", column = @Column(name = "user_id", nullable = false)) })
    public UserCompetencyId getId() {
        return this.id;
    }

    public void setId(UserCompetencyId id) {
        this.id = id;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "level_id")
    public Level getLevel() {
        return this.level;
    }

    public void setLevel(Level level) {
        this.level = level;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "user_id", nullable = false, insertable = false, updatable = false)
    public User getUser() {
        return this.user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @ManyToOne(fetch = FetchType.EAGER,cascade=CascadeType.ALL)
    @JoinColumn(name = "competency_id", nullable = false, insertable = false, updatable = false)
    public Competency getCompetency() {
        return this.competency;
    }

    public void setCompetency(Competency competency) {
        this.competency = competency;
    }
}   

用户能力标识

@Embeddable
public class UserCompetencyId implements java.io.Serializable {

    private Long competencyId;
    private Long userId;

    public UserCompetencyId() {
    }

    public UserCompetencyId(Long competencyId, Long userId) {
        this.competencyId = competencyId;
        this.userId = userId;
    }


    @Column(name = "competency_id", nullable = false)
    public Long getCompetencyId() {
        return this.competencyId;
    }

    public void setCompetencyId(Long competencyId) {
        this.competencyId = competencyId;
    }

    @Column(name = "user_id", nullable = false)
    public Long getUserId() {
        return this.userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public boolean equals(Object other) {
        if ((this == other))
            return true;
        if ((other == null))
            return false;
        if (!(other instanceof UserCompetencyId))
            return false;
        UserCompetencyId castOther = (UserCompetencyId) other;

        return (this.getCompetencyId() == castOther.getCompetencyId()) && (this.getUserId() == castOther.getUserId());
    }    
}

假设我已经在 User 和 Competency 表中进行了记录,并且我想关联我正在尝试这样发布的两者,但它给了我 405 Method Not Allowed 的错误。

需要帮助,要发布的 json 结构应该是什么用户已经存在并且能力可能存在,或者可以添加新的并与现有用户相关联。

【问题讨论】:

    标签: spring-boot spring-data-jpa spring-data-rest


    【解决方案1】:

    使用此代码,我可以发布新关系:

    UserCompetency.class

    @Entity
    @Table(name = "user_competency")
    @IdClass(UserCompetencyId.class)
    public class UserCompetency implements java.io.Serializable {
    
        @Id @ManyToOne
        @JoinColumn(name = "competency_id", nullable = false, insertable = false, updatable = false)
        private Competency competency;
    
        @Id @ManyToOne
        @JoinColumn(name = "user_id", nullable = false, insertable = false, updatable = false)
        private User user;
    

    UserCompetencyId.class

    public class UserCompetencyId implements java.io.Serializable {
    
        private Long competency;
    
        private Long user;
    
        public UserCompetencyId() {
        }
    
        public UserCompetencyId(Long competency, Long user) {
            this.competency = competency;
            this.user = user;
        }
    

    UserCompetencyRepository.class

    public interface UserCompetencyRepository extends JpaRepository<UserCompetency, UserCompetencyId> {
    
    }
    

    发布 http://localhost:8080/userCompetencies

    {
        "competency": "/competencies/2"
        , "user": "/user/4"
    }
    

    【讨论】:

    • 它计算出数据正在保存到复合表中,但我的 UserCompetency 类还有另一个属性,所以我在表中有其他列,即 level_id ,这也是外键,在顶部屏幕截图中给出了问题,请看一下,现在我应该如何在 json post private UserCompetencyId id 中发布级别 id;私人级别;私人用户用户;私人能力能力;
    • 添加, "level": "/level/123"?
    • 好的,实际上存储库类没有暴露给 Level 并且面临问题,我还需要问的是,如果我有一个现有用户并且我想添加新的能力,那么怎么办?它保存到能力表并通过 json post 将其与现有用户相关联,我将如何做到这一点。
    • 也可以是自定义控制器。或者两个 REST 调用。一个用于获取 competency 的新 ID,然后一个用于发布新的 userCompetencies 关系。
    • 我将如何对 userCompetencies 、复合表执行更新和删除
    【解决方案2】:

    显然,似乎没有“自然/简单”的方式来获得您想要的东西。但是有一个通过扩展序列化过程来集成嵌入式的有前途的项目:https://github.com/gregturn/embeddable-spring-data-rest

    • UserCompetencyIdJacksonModule, UserCompetencyIdSerializer, ..

    那么你应该可以从上面PATCH(不是POST)你的JSON。

    【讨论】:

    • 我已经下载了这个项目并尝试复制相同的更改,当我在主类上使用 @Import(RepositoryRestMvcConfiguration.class) 时遇到了一个问题,无法访问 api 端点并且当我访问 @ 987654322@ 它给出 404 not found 错误
    • 我认为RepositoryRestMvcConfiguration 将是必要的。但是其他的东西也对你没有帮助。所以我添加了一个新的答案..我们上周遇到的另一个问题..你能在哪里解决它?
    • 谢谢。我通过实现自定义控制器功能解决了这个问题。
    猜你喜欢
    • 2019-03-09
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 2021-02-05
    • 2017-10-16
    • 2014-08-31
    • 2021-10-19
    相关资源
    最近更新 更多