简体   繁体   中英

JPA ManyToMany bi-directional insert

I have problem and i could not find solution. I have bi-directional many to many anotation. I have this tables in DB (mariaDB):

  • item
  • section
  • item_section

Item part:

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "item_section",
        joinColumns = {
            @JoinColumn(name = "item", nullable = false, updatable = false)},
        inverseJoinColumns = {
            @JoinColumn(name = "section", nullable = false, updatable = false)})
private Set<Section> sections;

Section part:

@ManyToMany(fetch = FetchType.EAGER, mappedBy = "sections")
private Set<Item> items;

PROBLEM:

I create some Sections first. Than i want to create Item "within" this section. So i create instance of Item and add some existing Sections into set (Sections i get from DAO). If i persist the Item, records in item and item_section tables are created. But if i get some of affected section from DAO and iterate thru items set database changes are not here, Sections instances are in same state as before insert.

What did i wrong?

PS: i use eclipselink but i do not think it is interesting

SOLUTION

As @Chris said i called persist utimately but one side of direction already exist. No cascades was defined so during persist sections was not persisted nor merge. So best solution for my staless and JTA solution was use merge instead of persist on item and add MERGE cascade to sections collection...

Thanks everybody who came to help but especially to @Chris

It seems you are missing the attribute cascade=CascadeType.ALL. You should try to change

@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "item_section",
        joinColumns = {
            @JoinColumn(name = "item", nullable = false, updatable = false)},
        inverseJoinColumns = {
            @JoinColumn(name = "section", nullable = false, updatable = false)})
private Set<Section> sections;

to

@ManyToMany(cascade=CascadeType.ALL,fetch = FetchType.LAZY)
@JoinTable(name = "item_section",
        joinColumns = {
            @JoinColumn(name = "item", nullable = false, updatable = false)},
        inverseJoinColumns = {
            @JoinColumn(name = "section", nullable = false, updatable = false)})
private Set<Section> sections;

then it works normally.

I found this mistake via the tutorial Hibernate Many-To-Many Bidirectional Mapping Example

Hope this help

Problem may be in incorrect using of eclipselink's shared cache which is enabled by default. Try to disable it by adding in persistence.xml following:

<shared-cache-mode>NONE</shared-cache-mode>

When you persist or merge Section provider flushes it to database and add Section instance to shared cache so it can be retrieved from memory on next requests. When you persist Item you update only one side of the relationship, but the other side does not get updated, and becomes out of sync. In JPA, as in Java in general, it is the responsibility of the application or the object model to maintain relationships. If your application adds to one side of a relationship, then it must add to the other side. Read more about caching in bi-direction mapping in this article . I can offer following solutions of your problem:

  1. Disable cache for whole application in persistence.xml
  2. Manually refresh Section in DAO before retrieving it to user
  3. Use cache correctly by updating both sides of relationship:

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