如何在 Spring 中从将外键作为长属性引用的 json 创建模型?

Posted

技术标签:

【中文标题】如何在 Spring 中从将外键作为长属性引用的 json 创建模型?【英文标题】:How to create a model, in Spring, from json where the foreign key is referenced as a long attribute? 【发布时间】:2016-01-21 18:03:10 【问题描述】:

一个组有很多用户:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;

import javax.persistence.*;
import java.util.Collection;
import java.util.List;

@Entity
@Table(name = "GROUPS")
public class Group 

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

    @Column(name = "NAME")
    private String NAME;

    //@JsonManagedReference
    @OneToMany(mappedBy = "group"
            //, fetch = FetchType.EAGER
            //, cascade = CascadeType.ALL
    )
    private List<Users> itsUser;

    //getters and setters are omitted for clarity

用户

import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.fasterxml.jackson.annotation.JsonProperty;

import javax.persistence.*;
import static javax.persistence.GenerationType.SEQUENCE;

@Entity
@Table(name = "USERS")
@SequenceGenerator(name = "SEQUENCE_USER_ID",     //my own name in java (unique)
        sequenceName = "GENERATOR_SEQUENCE_USERS",     //in database
        initialValue = 1,
        allocationSize = 1)
public class Users 

    @JsonProperty(value = "id") //these play a role when both reading or writing
    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy=SEQUENCE, generator="SEQUENCE_USER_ID")
    private Long ID;

    @JsonProperty(value = "name")
    @Column(name="NAME")
    private String NAME;

    @JsonProperty(value = "username")
    @Column(name="USERNAME")
    private String USERNAME;

    @JsonProperty(value = "password")
    @Column(name="PASSWORD")
    private String PASSWORD;

    @JsonProperty(value = "email")
    @Column(name="EMAIL")
    private String EMAIL;

    @JsonProperty(value = "picture")    //Now it works with both mypic and picture as json keys
    @Column(name="PICTURE")
    private String PICTURE;

    //@Column(name="GROUP_ID")  //we already have a ManyToOne for this, we cannot repeat it
    @JsonProperty(value = "groups_id")
      //to ignore it in jpa (http://***.com/questions/1281952/jpa-fastest-way-to-ignore-a-field-during-persistence)
    private Long itsGroupId;

    @Transient
    public Long getItsGroupId() 
        if(itsGroupId == null) 
            this.itsGroupId = group.getID();
         else 
            //nop
        
        return itsGroupId;
    

    public void setItsGroupId(Long itsGroupId) 
        this.itsGroupId = itsGroupId;
    

    //@JsonIgnore
    //@JsonProperty(value = "groups_id")
    //@JsonBackReference
    @ManyToOne(optional = false, targetEntity = Group.class)
    @JoinColumn(
            name = "GROUP_ID",  //column name
            referencedColumnName = "ID"   //reference name
    )
    private Group group;

   //getters and setters are omitted for clarity

我们正在使用 SpringSpring-dataJackson 自动执行操作,但我们无法配置魔法:

我们试图同时坚持以下约束:

1) 保留对 groupId 和 ManyToOne 关系 group 的引用的能力。 这很容易通过将 @Transient 注释放在 groupId 上来实现,因为 @Column 是不允许的,因为我们已经声明了 @ManyToOne 注释.您还必须相应地实现 getGroupId 方法。

2) 返回包含 groups_idUsers 类的 json。 这可以通过设置 @JsonProperty 注释来实现。

3) 创建一个用户类,并将其保存在数据库中,通过一个json。 json 包含 groups_id,它的值是外键的整数。 这不起作用,因为通过在上面设置它 @Transient,系统会拒绝在数据库中保存临时的东西,或者至少这是我们解释这个异常的方式:

HTTP 状态 500 - 请求处理失败;嵌套异常是 org.springframework.dao.DataIntegrityViolationException: not-null 属性引用空值或瞬态值:com.pligor.mvctest.models.Users.group; 嵌套异常是 org.hibernate.PropertyValueException: 非空属性引用空值或瞬态值:com.pligor.mvctest.models.Users.group

【问题讨论】:

【参考方案1】:

在后端做这样的事情:

Group group = groupRepository.findById(userResource.getGroupId());
if (group != null) 
   User user = new User(userResource);
   user.setGroup(group);
   userRepository.save();

这背后的想法是您需要从数据库中获取组,以便能够将其与新创建的用户链接

【讨论】:

我们认为原始配置是问题所在,但我们猜测没有其他选择。谢谢 实际上,您可以通过创建一个仅设置其 ID 且所有其他字段为空的 Group 实例来使其比避免调用数据库更简单。如果您user.setGroup(group) 然后保存它仍然有效,但感谢您的回答 我们将开放回答以允许其他人提供更优雅的解决方案(如果有)。 如果您创建一个只定义了 ID 字段的新组,您可能会不小心删除有关该组的信息(如果您明确保存它,或者如果您的 flushMode 设置为 AUTO)

以上是关于如何在 Spring 中从将外键作为长属性引用的 json 创建模型?的主要内容,如果未能解决你的问题,请参考以下文章

Fluent NHibernate - 如何将外键列映射为属性

JOOQ:如何将外键解析为对象?

如何将外键添加到现有表?

实体 Remove() 将外键属性设置为 null

Django如何将外键传递给ModelForm字段

是否可以从将引用作为参数的 rust dll 导出函数