title: Spring Data JPA many to many save
body: <p>I'm using spring mvc + hibernate + spring data jpa.</p>
  
  <p>I have a many to many relationship between Person and SecurityRole. I want to add a new person using spring data jpa save method. When I try to save I am getting the following error:</p>
  
  <pre class="lang-none prettyprint-override"><code>SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/hub] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch update; SQL [insert into roles (RLE_ROLE, RLE_ID) values (?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update] with root cause
  com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
      at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
      at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
      at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
      at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
      at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
      at com.mysql.jdbc.Util.getInstance(Util.java:386)
      at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039)
      at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3597)
      at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3529)
      at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1990)
      at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2151)
      at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2625)
      at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2119)
      at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2415)
      at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1976)
      at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1449)
      at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)
      at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
      at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
      at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:114)
      at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109)
      at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244)
      at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2411)
      at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2874)
      at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
      at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
      at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
      at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
      at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
      at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
      at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
      at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:76)
      at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
      at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:521)
      at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:291)
      at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
      at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
      at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
      at com.sun.proxy.$Proxy59.save(Unknown Source)
      at com.motodoc.hub.service.SecurityUserServiceImpl.addNewUser(SecurityUserServiceImpl.java:64)
      at com.motodoc.hub.controller.UserController.save(UserController.java:150)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:483)
      at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
      at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
      at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:777)
      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:706)
      at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
      at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:644)
      at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:725)
  </code></pre>
  
  <p>It seems like the save method is trying to add a new SecurityRole and since a SecurityRole already exists with the same primary key hence the error. </p>
  
  <p>So my question is how do I save a new person, when given a SecurityRole which already exists in the database, it just updates only the Person and the mapping table ignoring the SecurityRole?</p>
  
  <p>Your help will be much appreciated.</p>
  
  <p>All the relevant code below...</p>
  
  <p>Person entity class:</p>
  
  <pre><code>@Entity
  @Table(name="persons")
  public class Person implements UserDetails {
  
      @Id
      @Column(name="PRS_ID")
      private int id;
  
      @NotEmpty
      @Column(name="PRS_USERNAME")
      private String username;
  
      @NotEmpty
      @Column(name="PRS_PASSWORD")
      private String password;
  
      @NotEmpty
      @Column(name="PRS_FIRST_NAME")
      private String firstName;
  
      @Column(name="PRS_MIDDLE_NAME")
      private String middleName;
  
      @NotEmpty
      @Column(name="PRS_LAST_NAME")
      private String lastName;
  
      @OneToMany(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
      @JoinTable(name = "USER_ROLES", joinColumns = { 
              @JoinColumn(name = "USR_PRS_ID") }, inverseJoinColumns = { 
              @JoinColumn(name = "RLE_ID") })
      private Set&lt;SecurityRole&gt; roles;
  
      @Transient
      private final String PERMISSION_PREFIX = "ROLE_PERM_";
  
      @Override
      public Collection&lt;? extends GrantedAuthority&gt; getAuthorities() {
          Set&lt;GrantedAuthorityImpl&gt; authorities = new HashSet&lt;GrantedAuthorityImpl&gt;();
          for (SecurityRole role : roles) {
              for (SecurityPermission permission : role.getPermissions()) {
                  GrantedAuthorityImpl authority = new GrantedAuthorityImpl(PERMISSION_PREFIX + permission.getPermission());
                  authorities.add(authority);
              }
          }
          return authorities;
      }
  </code></pre>
  
  <p>SecurityRole class:</p>
  
  <pre><code>@Entity
  @Table(name="roles")
  public class SecurityRole implements Serializable {
  
      @Id
      @Column(name="RLE_ID")
      private int id;
  
      @NotEmpty
      @Column(name="RLE_ROLE")
      private String role;
  
      @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
      @JoinTable(name = "ROLE_PERMISSIONS", joinColumns = { 
              @JoinColumn(name = "RLE_ID") }, inverseJoinColumns = { 
              @JoinColumn(name = "PRM_ID") })
      private Set&lt;SecurityPermission&gt; permissions;
  }
  </code></pre>
  
  <p>Service class</p>
  
  <pre><code>public class SecurityUserServiceImpl implements ISecurityUserService {
  
      @Autowired
      private IPersonDao personDao;
  
      @Autowired
      private IRoleDao roleDao;
  
      @Autowired
      private BCryptPasswordEncoder encoder;
  
      @Override
      public void addNewUser(AddUserForm addUserForm) {
  
          Person newPerson = addUserForm.getPerson();
  
          //encode password
          String encodedPassword = encoder.encode(newPerson.getPassword());
  
          //set the encoded password as the password
          newPerson.setPassword(encodedPassword);
  
          Set&lt;SecurityRole&gt; securityRoles = new HashSet&lt;SecurityRole&gt;();
  
          //get Role
          securityRoles.add(roleDao.findById(addUserForm.getRoleId()));
  
          newPerson.setRoles(securityRoles);
  
          //now save
          personDao.save(newPerson);
      }
  }
  </code></pre>
  
  <p>IPersonDao interface:</p>
  
  <pre><code>public interface IPersonDao extends JpaRepository&lt;Person, Long&gt;, QueryDslPredicateExecutor&lt;Person&gt; {
  
      @SuppressWarnings("unchecked")
      public Person save(Person person);
  
  }
  </code></pre>
  
  <p>IRoleDao interface:</p>
  
  <pre><code>public interface IRoleDao extends JpaRepository&lt;SecurityRole, Long&gt;, QueryDslPredicateExecutor&lt;SecurityRole&gt; {
  
      public List&lt;SecurityRole&gt; findAll();
  
      public SecurityRole findById(int id);
  
  }
  </code></pre>
  
  <p>Persistence.xml file:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"&gt;
      &lt;persistence-unit name="hibernatePersistenceUnit" transaction-type="RESOURCE_LOCAL"&gt;
          &lt;properties&gt;
              &lt;property name="hibernate.hbm2ddl.auto" value="update" /&gt;
              &lt;property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" /&gt;
          &lt;/properties&gt;
          &lt;!-- &lt;mapping-file&gt;META-INF/orm.xml&lt;/mapping-file&gt;  --&gt;
      &lt;/persistence-unit&gt;
  &lt;/persistence&gt;
  </code></pre>