I have two entities that have these fields:
Code entity:
@Entity
@Table(name = "snippets")
@NoArgsConstructor
@Getter
@Setter
public class Code {
private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
@Id
@GeneratedValue
private Long id;
private String code;
private String date;
private User author;
private List<User> allowedUsers;
public Code(CodeDto code) {
this.code = code.getCode();
this.date = LocalDateTime.now().format(formatter);
this.author = code.getAuthor();
}
}
User entity:
@Entity
@Table(name = "users")
@Getter
@Setter
@EqualsAndHashCode
@NoArgsConstructor
public class User implements UserDetails {
@Id
@GeneratedValue
private Long id;
private String username;
private String password;
@Enumerated(EnumType.STRING)
private UserRole userRole;
@Transient
private boolean locked;
private boolean enabled = true;
private List<Code> codeList;
public User(String username, String password, UserRole userRole) {
this.username = username;
this.password = password;
this.userRole = userRole;
}
}
I am trying to create an application similar to github (but very simplified of course). I want each user to be able to add a code snippet, and later grant access to it to other users. I want to store the information who is the author and who has access to each code snippet. How can I achieve that?
These relationships can be represented using this:
@OneToMany @JoinColumn(name = "code_id", referencedColumnName = "id")
private List<Code> codeList;
The same can be done for the other:
@OneToMany @JoinColumn(name = "user_id", referencedColumnName = "id")
private List<User> allowedUsers;
I want each user to be able to add a code snippet
I'm assuming you actually mean multiple code snippets, which would be more sensible. To achieve that you would need a OneToMany association between the User and Code, for which you would use @OneToMany.
You haven't mentioned the persistence provider you're using, but at least for Hibernate, I would suggest a bi-directional relation to avoid an extra update query when adding a Code.
When the relation is bi-directional, the @ManyToOne side of the relation, aka the owner side, is in charge of filling the foreign key column on the entity's insert, more here .
public class User implements UserDetails {
...
@OneToMany(mappedBy = "writer")
private Set<Code> codeList = new HashSet<>();
public void addCode(Code code) {
codeList.add(code);
code.setWriter(this);
}
public void removeCode(Code code) {
codeList.remove(code);
code.setWriter(null);
}
}
As we said, the association is bi-directional, so on the Code side, you would have:
public class Code {
...
@ManyToOne(fetch = FetchType.LAZY)
private User writer;
}
PS1: I switched list to set as it's the recommendation, morehere .
PS2: Dealing with bi-directional OneToMany relations can be tricky, ie forgetting to set the writer side in our example will result in a null foreign key in the database. A nice way to avoid that is to have helper methods to add and remove a child entity.
and later grant access to it to other users
For this, the association would be a @ManyToMany, in order to map it to a join table for in the database :
public class Code {
...
@ManyToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE})
@JoinTable(name = "code_viewers",
joinColumns = @JoinColumn(name = "code_id"),
inverseJoinColumns = @JoinColumn(name = "viewer_id"))
private Set<User> viewers = new HashSet<>();
}
Once more, you need to set the other side of the relation:
public class User implements UserDetails {
...
@ManyToMany(mappedBy = "viewers")
private Set<Code> accessibleCodes = new HashSet<>();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.