简体   繁体   中英

Many-to-Many Relationship in Hibernate with Extra Column

I have database stucture like this. It is for user access control in my application.

 UserGroup
 ==========
 id (PK)
 code
 name


 HakAkses
 ==========
 id(PK)
 UserGroup_id (FK)
 Akses_id (FK) 
 action_create
 action_read
 action_update
 action_delete


 Akses
 ==========
 id(PK)
 code

And I make the hibernate annotation like this

@Entity
@Table(name = "[Master].[UserGroup]")
public class UserGroup implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(unique = true, length = 10)
    private String kode;
    private String nama;

    @OneToMany(mappedBy = "userGroup")
    private Set<HakAkses> hakAksesSet;
}

@Entity
@Table(name = "[master].[HakAkses]")
public class HakAkses implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "UserGroup_id", nullable = false)
    private UserGroup userGroup;

    @ManyToOne
    @JoinColumn(name = "Akses_id", nullable = false)
    private Akses akses;

    @Column(name = "action_create")
    private boolean canCreate;
    @Column(name = "action_read")
    private boolean canRead;
    @Column(name = "action_update")
    private boolean canUpdate;
    @Column(name = "action_delete")
    private boolean canDelete;
}

@Entity
@Table(name = "[master].[Akses]")
public class Akses implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(unique = true)
    private String kode;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "akses")
    private List<HakAkses> hakAksesSet;
}

And then I tried in my tester with this code

UserGroup userGroup = new UserGroup(kode, nama);
userGroup.setHakAksesSet(new HashSet<HakAkses>(hakAksesList));
this.controller.save(userGroup);

But when I run the tester, the data was saved in database only UserGroup data. Is there any problem with my hibernate annotation?

Thank you

This is because the cascade annotation is missing on the parent entity. See if this helps

@Table(name = "[Master].[UserGroup]")
public class UserGroup implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(unique = true, length = 10)
    private String kode;
    private String nama;

    @OneToMany(mappedBy = "userGroup", cascade = CascadeType.ALL)
    private Set<HakAkses> hakAksesSet;
}

Your mapping uses mappedBy , which among other settings, does inject the inverse="true" setting to the one-to-many end. Read more about this here:

In a nutshell, that means, that Hibernate is instructed: the other (many-to-one) end will care about persisting. Also, try to go through this example in documentation

23.2. Bidirectional one-to-many

This example shows inverse in action, some essential cites:

... Now that the Child entity is managing the state of the link, we tell the collection not to update the link. We use the inverse attribute to do this:

<set name="children" inverse="true">
    <key column="parent_id"/>
    <one-to-many class="Child"/>
</set>

The following code would be used to add a new Child:

Parent p = (Parent) session.load(Parent.class, pid);
Child c = new Child();
c.setParent(p);
p.getChildren().add(c);
session.save(c);
session.flush();

Only one SQL INSERT would now be issued.

So what we see there?

  • inverse setting is what we need. It improves performance (and we have it due to mappedBy)
  • but it is not enough to set the relation on the one-to-many side. We MUST set a parent to each child .

So, you should extend this:

UserGroup userGroup = new UserGroup(kode, nama);
userGroup.setHakAksesSet(new HashSet<HakAkses>(hakAksesList));
// this is not enough - we also MUST 
// FOR each HakAkses in the  list 
// SET a Parent, i.e hakAksses.setUserGroup(userGroup)

Finally, there (almost) always should be cascading turned on. One should not care about that manually:

@OneToMany(mappedBy = "userGroup", cascade = CascadeType.ALL)

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