简体   繁体   中英

Hibernate Many To Many unidirectional mapping

I have two tables USERS and FILES. I want to be able to control the users that can download a file, and for this I was thinking of creating and intermediary table FILE_PERMISSIONS with a user_id and a file_id.

Looking at database level I understand how can I solve the problem, but going up at Hibernate level, I can't really understand how should I map this relation. The way I see it is something like this:

public class User {
   private Integer userId;
}

public class File {
   private Integer fileId;
   private List<Integer> userIds;
}

So I want my File object to know the id property of all the users that can download the file, but not vice versa, so that a user doesn't know about those files.

From what I read I can use a many to many unidirectional relation but I'm not sure that I can only have the id of the user, and not the user object itself.

You can manage it having the following structure.

User:

@Entity
public class User {
    @Id
    private Integer userId;

    // getters, setters
}

File:

@Entity
public class File {
    @Id
    private Integer fileId;

    @ManyToMany
    @JoinTable(
            name = "file_permissions",
            joinColumns = @JoinColumn(name = "file_id"),
            inverseJoinColumns = @JoinColumn(name = "user_id")
    )
    private Set<User> users;

    // getters, setters
}

You can benefit from making an easier design using @OneToMany relationship instead. This way you could create a service in order to manage File permissions, instead of relying on user service or file services to do so.

I propose something like:

User.java

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Version
    private Integer version;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
    private List<FilePermissions> filePermissionsList= new ArrayList<>();


    public Integer getId() {
        return id;
    }

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

    public List<FilePermissions> getFilePermissionsList() {
        return filePermissionsList;
    }

    public void setFilePermissionsList(List<FilePermissions> filePermissionsList) {
        this.filePermissionsList = filePermissionsList;
    }
}

Notice User has a list of FilePermissions.

Your FilePermission class should be like:

@Entity
public class FilePermissions {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Version
    private Integer version;

    @ManyToOne
    private User user;

    @OneToOne
    private File file;

    private Permission permission;


    public FilePermissions() {

    }

    public FilePermissions(User user, File file, Permission permission) {
        this.user = user;
        this.file = file;
        this.permission = permission;
    }

    public Integer getId() {
        return id;
    }

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

    public Integer getVersion() {
        return version;
    }

    public void setVersion(Integer version) {
        this.version = version;
    }

    public User getUser() {
        return user;
    }

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

    public File getFile() {
        return file;
    }

    public void setFile(File file) {
        this.file = file;
    }

    public Permission getPermission() {
        return permission;
    }

    public void setPermission(Permission permission) {
        this.permission = permission;
    }
}

Notice the @ManytoOne relationship back to the user, as well as the @OneToOne relationship to the File class. Here you can store the detail on what permission user have, in this case i have a enumeration.

Your File class is straight forward:

@Entity
public class File {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Version
    private Integer version;

    private String name;

    public File() {}

    public File(String name) {
        this.name = name;
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

You can see solution in detail here: https://github.com/ccoloradoc/HibernateFilePermissionSample

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM