Search code examples
javamysqljpaeclipselink

No new entry in join table of many to many relationship JPA


I am trying to persist new entry of file object that has many to many relationship between user and department (many user/Department can access file in this scenario) but after persisting the information, in the join table of user_fileobject and dept_fileobject are not reflected. The persist itself and the instantiate list of users and departments are on different classes, but do these lists need to be persisted as well?

Here are the code of instantiate the list of users and departments:

for(int i=0; i<listSharee.length; i++){
                                String username = listSharee[i].replace(" ", ".").toLowerCase();
                                Query q1 =  CpabeDAO.em.createQuery("SELECT u FROM User u WHERE u.username=:username");
                                q1.setParameter("username", username);
                                List<User> userReq = q1.getResultList();
                                if(userReq.isEmpty()){
                                    Query q3 =  CpabeDAO.em.createQuery("SELECT d FROM Department d WHERE d.departmentName=:name");
                                    q3.setParameter("name", listSharee[i]);
                                    List<Department> departmentReq = q3.getResultList();
                                    for(Department dept : departmentReq){
                                        listSharee[i] = listSharee[i].replace(" ", "");
                                        departmentSharee.add(dept);

                                    }
                                }else{
                                    for(User user: userReq){
                                        userSharee.add(user);
                                        listSharee[i] = listSharee[i].replace(" ", "_");

                                    }
                                }
                            }
...
    FileUpload.uploadFile(file, totalPolicy, userLoggedIn, userSharee, departmentSharee);

Here is the code for persisting the information of file object:

public static void storeFileInformation(byte[] encryptedRawFileKey, String fileChecksum, String fileKeyChecksum, byte[] ivFileKey, String keyName, String realName, String policy,  User owner, List<User> userSharee, List<Department> departmentSharee ){
//      byte[] encryptedRawFileKey, String fileChecksum, String fileKeyChecksum, byte[] ivFileKey, String keyName, List<User> listUserAccessor, List<Policy> policies, String realName, User userCreator
        CpabeDAO.em.getTransaction().begin();

        FileObject fileObject = new FileObject();
        fileObject.setEncryptedRawFileKey(encryptedRawFileKey);
        fileObject.setFileChecksum(fileChecksum);
        fileObject.setFileKeyChecksum(fileKeyChecksum);
        fileObject.setIvFileKey(ivFileKey);
        fileObject.setKeyName(keyName);
        fileObject.setPolicy(policy);
        fileObject.setRealName(realName);
        fileObject.setListDeptAccessor(departmentSharee);
        fileObject.setListUserAccessor(userSharee);
        fileObject.setUserCreator(owner);

        CpabeDAO.em.persist(fileObject);
        CpabeDAO.em.getTransaction().commit();
        CpabeDAO.em.close();
    }

Here are the POJO of User, Department and FileObject classes:

@Entity

public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    public int id;
    public String username;
    public String firstname;
    public String lastname;
//  public String attributes;
    public String hashPassword;

    @ManyToOne
    private Department department;

    @OneToMany(mappedBy = "user")
    public List<Device> devices = new ArrayList<Device>();

    @OneToMany(mappedBy = "userCreator")
    public List <FileObject> fileOwned = new ArrayList <FileObject>();

    @ManyToMany
    @JoinTable(name="USER_FILE_ACCESS",
    joinColumns=@JoinColumn(name="user_id"),
       inverseJoinColumns=@JoinColumn(name="fileHasAccess_ID "))
    public List<FileObject> fileHasAccess = new ArrayList<FileObject>();
}

@Entity
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    int departmentId;
    String departmentName;

    @OneToMany(mappedBy = "department")
    private List<User> employees = new ArrayList<User>();


    @ManyToMany
    @JoinTable(name="DEPT_FILE_ACCESS",
    joinColumns=@JoinColumn(name="dept_id"),
       inverseJoinColumns=@JoinColumn(name="fileHasAccess_ID "))
    public List<FileObject> deptFileHasAccess = new ArrayList<FileObject>();
    }

@Entity
public class FileObject {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    public int id;

    String fileChecksum;

    String fileKeyChecksum;

    String realName;

    String keyName;

//  @OneToMany(mappedBy = "fileObject")
//  public List<Policy> policies = new ArrayList<Policy>();

    String policy;

    byte[] encryptedRawFileKey;

    byte[] ivFileKey;

    @ManyToOne
    public User userCreator;

    @ManyToMany(mappedBy="fileHasAccess")
    public List<User> listUserAccessor = new ArrayList<User>();

    @ManyToMany(mappedBy="deptFileHasAccess")
    public List<Department> listDeptAccessor = new ArrayList<Department>();
}

Is there something wrong with the code itself?


Solution

  • You have to populate each of the User / Department entities with the newly created FileObject:

            fileObject.setRealName(realName);
            fileObject.setListDeptAccessor(departmentSharee);
            fileObject.setListUserAccessor(userSharee);
            fileObject.setUserCreator(owner);
    
            for(Department dep: departmentSharee){
                dep.getFileHasAccess().add(fileObject);
            } 
    
            for(User user: userSharee){
                user.getDeptFileHasAccess().add(fileObject);
            } 
    

    You can also try adding cascade option like following:

    @ManyToMany(mappedBy="fileHasAccess", cascade = {CascadeType.PERSIST, CascadeType.MERGE})