One Group has many Users:
Group
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
}
Users
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://stackoverflow.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
}
We are using Spring with Spring-data and Jackson to do things automagically but we cannot configure the magic:
We are trying to stick on the following constraints at the same time:
1) Keep the ability to have a reference to the groupId and the ManyToOne relationship group.
This is easy to be achieved by putting @Transient annotation at the groupId because @Column is not allowed since we have already declared the @ManyToOne annotation. You also have to implement the getGroupId method accordingly.
2) Return a json of Users class that contains the groups_id.
This can be implemented by setting the @JsonProperty annotation.
3) Create a user class, and also save it in the database, by a json. The json contains groups_id which has as a value an integer for the foreign key.
This does not work because by setting it @Transient above, then the system refuses to save in the database something that is transient or at least this is how we interpret this exception:
HTTP Status 500 - Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: com.pligor.mvctest.models.Users.group; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: com.pligor.mvctest.models.Users.group