title: Why this Hibernate mapping is inserting all the relationship except this "second level" Many To Many relationship?
body: <p>I am working on a Spring Boot project using Spring Data JPA and I am finding the following problem trying to correctly map some pre-existing database tables on entity classes.</p>
  <p>In particualr I am finding some difficulties trying to map a specific <strong>Many To Many</strong> relationship (It is strange because I was able to do a similar mapping in the same example).</p>
  <p>My DB tables are something like this:</p>
  <p><a href="https://i.stack.imgur.com/R7raf.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/R7raf.png" alt="enter image description here" /></a></p>
  <p><strong>NOTE:</strong> the  <strong>user_type</strong> and <strong>operation</strong> tables are typological and contains fixed values.</p>
  <p>My problem is that the <strong>Many To Many</strong> relationship between <strong>UserType</strong> and <strong>Operation</strong> table is not working on my code.</p>
  <p>Following my classes (the table's name are slightly different on the DB):</p>
  <ol>
  <li><p><strong>User</strong>: it represents a user on a portal:</p>
  <p>@Entity
  @Table(name = &quot;portal_user&quot;)
  @Getter
  @Setter
  public class User implements Serializable {</p>
  <pre><code> private static final long serialVersionUID = 5062673109048808267L;
  
   @Id
   @Column(name = &quot;id&quot;)
   @GeneratedValue(strategy=GenerationType.IDENTITY)
   private int id;
  
   @Column(name = &quot;first_name&quot;)
   private String firstName;
  
   @Column(name = &quot;middle_name&quot;)
   private String middleName;
  
   @Column(name = &quot;surname&quot;)
   private String surname;
  
   @Column(name = &quot;sex&quot;)
   private char sex;
  
   @Column(name = &quot;birthdate&quot;)
   private Date birthdate;
  
   @Column(name = &quot;tex_code&quot;)
   private String taxCode;
  
   @Column(name = &quot;e_mail&quot;)
   private String eMail;
  
   @Column(name = &quot;contact_number&quot;)
   private String contactNumber;
  
   @Temporal(TemporalType.DATE)
   @Column(name = &quot;created_at&quot;)
   private Date createdAt;
  
   @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = &quot;user&quot;, orphanRemoval = true)
   @JsonManagedReference
   private Set&lt;Address&gt; addressesList = new HashSet&lt;&gt;();
  
   @ManyToMany(cascade = { CascadeType.MERGE })
   @JoinTable(
       name = &quot;portal_user_user_type&quot;, 
       joinColumns = { @JoinColumn(name = &quot;portal_user_id_fk&quot;) }, 
       inverseJoinColumns = { @JoinColumn(name = &quot;user_type_id_fk&quot;) }
   )
   Set&lt;UserType&gt; userTypes;
  
  
  
   public User(String firstName, String middleName, String surname, char sex, Date birthdate, String taxCode,
           String eMail, String contactNumber, Date createdAt) {
       super();
       this.firstName = firstName;
       this.middleName = middleName;
       this.surname = surname;
       this.sex = sex;
       this.birthdate = birthdate;
       this.taxCode = taxCode;
       this.eMail = eMail;
       this.contactNumber = contactNumber;
       this.createdAt = createdAt;
   }
  </code></pre>
  <p>}</p>
  </li>
  </ol>
  <p><strong>NOTE:</strong> It contains this <strong>Many To Many</strong> relationship between the <strong>portal_user</strong> table (mapped by <strong>User</strong>) and the ** user_type** table (mapped by **UserType). It works fine, the problem is not here.</p>
  <pre><code>@ManyToMany(cascade = { CascadeType.MERGE })
  @JoinTable(
      name = &quot;portal_user_user_type&quot;, 
      joinColumns = { @JoinColumn(name = &quot;portal_user_id_fk&quot;) }, 
      inverseJoinColumns = { @JoinColumn(name = &quot;user_type_id_fk&quot;) }
  )
  Set&lt;UserType&gt; userTypes;
  </code></pre>
  <ol start="2">
  <li><p><strong>Address</strong>: an user can have multiple addesses:</p>
  <p>@Entity
  @Table(name = &quot;address&quot;)
  @Getter
  @Setter
  @NoArgsConstructor
  @AllArgsConstructor
  public class Address implements Serializable {</p>
  <pre><code> private static final long serialVersionUID = 6956974379644960088L;
  
   @Id
   @Column(name = &quot;id&quot;)
   @GeneratedValue(strategy=GenerationType.IDENTITY)
   private int id;
  
   @Column(name = &quot;country&quot;)
   private String country;
  
   @Column(name = &quot;province&quot;)
   private String province;
  
   @Column(name = &quot;zip_code&quot;)
   private String zipCode;
  
   @Column(name = &quot;street&quot;)
   private String street;
  
   @Column(name = &quot;notes&quot;)
   private String notes;
  
  
   @ManyToOne
   @EqualsAndHashCode.Exclude          // Needed by Lombock in &quot;Many To One&quot; relathionship to avoid error
   @JoinColumn(name = &quot;fk_user_id&quot;, referencedColumnName = &quot;id&quot;)
   @JsonBackReference
   private User user;
  
   public Address(String country, String province, String zipCode, String street, String notes, User user) {
       super();
       this.country = country;
       this.province = province;
       this.zipCode = zipCode;
       this.street = street;
       this.notes = notes;
       this.user = user;
   }
  </code></pre>
  <p>}</p>
  </li>
  <li><p><strong>UserType</strong>: it represents a type of user.</p>
  <p>@Entity
  @Table(name = &quot;user_type&quot;)
  @Getter
  @Setter
  public class UserType implements Serializable {</p>
  <pre><code> private static final long serialVersionUID = 6904959949570501298L;
  
   @Id
   @Column(name = &quot;id&quot;)
   @GeneratedValue(strategy=GenerationType.IDENTITY)
   private int id;
  
   @Column(name = &quot;type_name&quot;)
   private String typeName;
  
   @Column(name = &quot;description&quot;)
   private String description;
  
   @ManyToMany(cascade = { CascadeType.MERGE })
   @JoinTable(
       name = &quot;user_type_operation&quot;, 
       joinColumns = { @JoinColumn(name = &quot;fk_user_type_id&quot;) }, 
       inverseJoinColumns = { @JoinColumn(name = &quot;fk_operation_id&quot;) }
   )
   Set&lt;Operation&gt; operations;
  
  
   public UserType() {
       super();
       // TODO Auto-generated constructor stub
   }
  
   public UserType(String typeName, String description) {
       super();
       this.typeName = typeName;
       this.description = description;
   }
  </code></pre>
  <p>}</p>
  </li>
  </ol>
  <p><strong>NOTE:</strong> HERE IS WHEERE I FOUND A PROBLEM as you can see this contains this <strong>Many To Many</strong> relationship betwenn <strong>user_type</strong> table (mapped by **UserType) and the <strong>operation</strong> table (mapped by **Operation). This is a many to many relationship because a specific user type can have multiple possible operation and an operation can be related to multiple user types).</p>
  <pre><code>@ManyToMany(cascade = { CascadeType.MERGE })
  @JoinTable(
      name = &quot;user_type_operation&quot;, 
      joinColumns = { @JoinColumn(name = &quot;fk_user_type_id&quot;) }, 
      inverseJoinColumns = { @JoinColumn(name = &quot;fk_operation_id&quot;) }
  )
  Set&lt;Operation&gt; operations;
  </code></pre>
  <p>The problem is that all the information are saved in my database except this last relationship.</p>
  <p>to test it I created this JUnit test method:</p>
  <pre><code>@SpringBootTest()
  @ContextConfiguration(classes = GetUserWsApplication.class)
  @TestMethodOrder(OrderAnnotation.class)
  public class UserRepositoryTest {
      
      @Autowired
      private UsersRepository userRepository;
      
      @Autowired 
      UserTypeRepository userTypeRepository;
      
      @Autowired
      OperationRepository operationRepository;
      
      
      @Test
      @Order(1)
      public void testInserAdmintUser() {
          
          //System.out.println(10/0); 
          User user = new User(&quot;Luca&quot;, null, &quot;Verdi&quot;, 'M', new Date(), &quot;XXX&quot;, &quot;xxx@gmail.com&quot;, &quot;329123456&quot;, new Date());
          
          Set&lt;Address&gt; addressesList = new HashSet&lt;&gt;();
          addressesList.add(new Address(&quot;Italy&quot;, &quot;RM&quot;, &quot;00100&quot;, &quot;Via XXX 123&quot;, &quot;near YYY&quot;, user));
          
          user.setAddressesList(addressesList);
          
          List&lt;UserType&gt; userTypesList = userTypeRepository.findAll();
          
          List&lt;Operation&gt; operationsList = operationRepository.findAll();
          Set&lt;Operation&gt; operationSet = new HashSet&lt;Operation&gt;();
          operationSet.add(operationsList.get(0));                        // Constains only ADMIN OPERATION
          
          //Set&lt;UserType&gt; userTypesSet = new HashSet&lt;UserType&gt;(userTypesList);
          Set&lt;UserType&gt; userTypesSet = new HashSet&lt;UserType&gt;();
          
          userTypesList.get(0).setOperations(operationSet);
          
          userTypesSet.add(userTypesList.get(0));                     // Contains only ADMIN user type
          
          user.setUserTypes(userTypesSet);    
          
          userRepository.save(user);
          assertTrue(true);
          
      }
      
  }
  </code></pre>
  <p>In this method I first set a list of addresses on the <strong>User</strong> instance that is the main object that must be persisted.</p>
  <p>Then I set a <strong>UserType</strong> list (at the moment only a specific type related to the <strong>ADMIN</strong> type) and I associate a specific operation to this user type.</p>
  <p>Running this method, before persist the object with the <strong>save()</strong> method I inspected the <strong>user</strong> object to be saved with the debugger and I obtained this:</p>
  <pre><code>user    (id=124)    
      addressesList   HashSet&lt;E&gt;  (id=146)    
      birthdate   Date  (id=148)  
      contactNumber   329123456&quot; (id=151) 
      createdAt   Date  (id=156)  
      eMail   xxx@gmail.com&quot; (id=157) 
      firstName   Luca&quot; (id=158)  
      id  0   
      middleName  null    
      sex M   
      surname Verdi&quot; (id=159) 
      taxCode XXX&quot; (id=160)   
      userTypes   HashSet&lt;E&gt;  (id=131)    
          [0] UserType  (id=143)  
              description Admin user type !!!&quot; (id=164)   
              id  7   
              operations  HashSet&lt;E&gt;  (id=166)    
              typeName    ADMIN&quot; (id=167) 
  Add new expression  
  </code></pre>
  <p>So as you can see it contains all the information including:</p>
  <ul>
  <li>The <strong>userTypes</strong> HashSet: this information will be correctly stored into my <strong>portal_user_user_type</strong> Many To Many relationship table.</li>
  <li>The <strong>userTypes --&gt; operations</strong> HashSet: HERE MY PROBLEM. This information is not stored into <strong>user_type_operation</strong> Many To Many relationship table.</li>
  </ul>
  <p>My unit test method doesn't fail. I have no exception. All the information are correctly stored into the DB except the information that represent this <strong>Many To Many</strong> relationship defined into the <strong>UserType</strong> entity class:</p>
  <pre><code>@ManyToMany(cascade = { CascadeType.MERGE })
  @JoinTable(
      name = &quot;user_type_operation&quot;, 
      joinColumns = { @JoinColumn(name = &quot;fk_user_type_id&quot;) }, 
      inverseJoinColumns = { @JoinColumn(name = &quot;fk_operation_id&quot;) }
  )
  Set&lt;Operation&gt; operations;
  </code></pre>
  <p>This is the Hibernate output in my console:</p>
  <pre><code>USER: com.easydefi.users.entity.User@6e4bccc
  Hibernate: 
      insert 
      into
          portal_user
          (birthdate, contact_number, created_at, e_mail, first_name, middle_name, sex, surname, tex_code) 
      values
          (?, ?, ?, ?, ?, ?, ?, ?, ?)
  Hibernate: 
      insert 
      into
          address
          (country, notes, province, street, fk_user_id, zip_code) 
      values
          (?, ?, ?, ?, ?, ?)
  Hibernate: 
      insert 
      into
          portal_user_user_type
          (portal_user_id_fk, user_type_id_fk) 
      values
          (?, ?)
  </code></pre>
  <p>As you can see it seems that it is performing all the INSERT query except the one that have to insert into the <strong>user_type_operation</strong></p>
  <p>Why? What could be wrong? What am I missing? How can I try to fix this issue in order to fix this problem?</p>