如何在 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
我们正在使用 Spring 与 Spring-data 和 Jackson 自动执行操作,但我们无法配置魔法:
我们试图同时坚持以下约束:
1) 保留对 groupId 和 ManyToOne 关系 group 的引用的能力。 这很容易通过将 @Transient 注释放在 groupId 上来实现,因为 @Column 是不允许的,因为我们已经声明了 @ManyToOne 注释.您还必须相应地实现 getGroupId 方法。
2) 返回包含 groups_id 的 Users 类的 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 创建模型?的主要内容,如果未能解决你的问题,请参考以下文章