title: Cannot save many-to-many relationship in Hibernate
body: <p>I'm learning hibernate, but I can't save many-to-many relationships. I use hibernate 4.1.8 and spring 3.1.3</p>
  
  <p>tables</p>
  
  <pre><code>CREATE TABLE `t_role` (
  `pk_role_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `code` varchar(45) DEFAULT NULL,
  `description` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`pk_role_id`)
  ) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8$$
  
  CREATE TABLE `t_user` (
  `pk_user_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `login_name` varchar(45) DEFAULT NULL,
  `email` varchar(45) DEFAULT NULL,
  `password` varchar(45) DEFAULT NULL,
  `ordercode` int(11) DEFAULT NULL,
  PRIMARY KEY (`pk_user_id`),
  KEY `fk0983` (`pk_user_id`)
  ) ENGINE=InnoDB AUTO_INCREMENT=99 DEFAULT CHARSET=utf8$$
  
  CREATE TABLE `t_user_role` (
  `pk_user_id` bigint(20) NOT NULL,
  `pk_role_id` bigint(20) NOT NULL,
  PRIMARY KEY (`pk_user_id`,`pk_role_id`)
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8$$here
  </code></pre>
  
  <p>applicationContext.xml</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
      xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/util
       http://www.springframework.org/schema/util/spring-util-3.0.xsd
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"&gt;
  
      &lt;bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
          destroy-method="close"&gt;
          &lt;property name="driverClass" value="com.mysql.jdbc.Driver" /&gt;
          &lt;property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/myssh" /&gt;
          &lt;property name="user" value="root" /&gt;
          &lt;property name="password" value="" /&gt;
          &lt;property name="minPoolSize" value="5" /&gt;
          &lt;property name="maxPoolSize" value="15" /&gt;
          &lt;property name="initialPoolSize" value="3" /&gt;
          &lt;property name="maxIdleTime" value="10" /&gt;
          &lt;property name="acquireIncrement" value="3" /&gt;
          &lt;property name="maxStatements" value="0" /&gt;
          &lt;property name="idleConnectionTestPeriod" value="60" /&gt;
          &lt;property name="acquireRetryAttempts" value="30" /&gt;
          &lt;property name="breakAfterAcquireFailure" value="false" /&gt;
          &lt;property name="testConnectionOnCheckout" value="false" /&gt;
      &lt;/bean&gt;
  
      &lt;!-- Hibernate SessionFactory --&gt;
      &lt;bean id="sessionFactory"
          class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"&gt;
          &lt;property name="dataSource"&gt;
              &lt;ref local="dataSource" /&gt;
          &lt;/property&gt;
          &lt;property name="annotatedClasses"&gt;
              &lt;list&gt;
                  &lt;value&gt;demo.myssh.model.User&lt;/value&gt;
                  &lt;value&gt;demo.myssh.model.Role&lt;/value&gt;
              &lt;/list&gt;
          &lt;/property&gt;
          &lt;property name="hibernateProperties"&gt;
              &lt;props&gt;
                  &lt;prop key="hibernate.dialect"&gt;org.hibernate.dialect.MySQL5Dialect&lt;/prop&gt;
                  &lt;prop key="hibernate.show_sql"&gt;true&lt;/prop&gt;
                  &lt;prop key="hibernate.format_sql"&gt;false&lt;/prop&gt;
                  &lt;prop key="hibernate.generate_statistics"&gt;true&lt;/prop&gt;
                  &lt;prop key="hibernate.autoReconnect"&gt;true&lt;/prop&gt;
                  &lt;prop key="hibernate.max_fech_depth"&gt;5&lt;/prop&gt;
                  &lt;prop key="hibernate.jdbc.batch_size"&gt;50&lt;/prop&gt;
                  &lt;prop key="hibernate.jdbc.fetch_size"&gt;100&lt;/prop&gt;
                  &lt;prop key="javax.persistence.validation.mode"&gt;none&lt;/prop&gt;
                  &lt;prop key="hibernate.current_session_context_class"&gt;org.springframework.orm.hibernate4.SpringSessionContext
                  &lt;/prop&gt;
              &lt;/props&gt;
          &lt;/property&gt;
      &lt;/bean&gt;
  
      &lt;tx:annotation-driven /&gt;
  
      &lt;bean id="transactionManager"
          class="org.springframework.orm.hibernate4.HibernateTransactionManager"&gt;
          &lt;property name="sessionFactory" ref="sessionFactory" /&gt;
      &lt;/bean&gt;
  
      &lt;bean id="user" class="demo.myssh.model.User"&gt;&lt;/bean&gt;
      &lt;bean id="message" class="demo.myssh.model.Message"&gt;&lt;/bean&gt;
      &lt;bean id="role" class="demo.myssh.model.Role"&gt;&lt;/bean&gt;
  &lt;/beans&gt;
  </code></pre>
  
  <p>user</p>
  
  <pre><code>package demo.myssh.model;
  
  import java.util.HashSet;
  import java.util.Set;
  import javax.persistence.*;
  
  @Entity
  @Table(name = "t_user")
  public class User implements java.io.Serializable {
  
      // Fields
      private static final long serialVersionUID = 3302763173315884925L;
  
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      @Column(name = "pk_user_id", unique = true, nullable = true)
      private Long userID;
  
      @Column(name = "login_name", length = 45)
      private String loginName;
  
      @Column(name = "email", length = 45)
      private String email;
  
      @Column(name = "password", length = 45)
      private String password;
  
      @Column(name = "ordercode")
      private Integer orderCode;
  
      @ManyToMany(cascade = { CascadeType.ALL })
      @JoinTable(name = "t_user_role", 
          joinColumns = { @JoinColumn(name = "pk_user_id") }, 
          inverseJoinColumns = { @JoinColumn(name = "pk_role_id") })
      private Set&lt;Role&gt; roles = new HashSet&lt;Role&gt;();
  
      public User() {
      }
  ...set,get...
  </code></pre>
  
  <p>role</p>
  
  <pre><code>package demo.myssh.model;
  
  import java.util.HashSet;
  import java.util.Set;
  import javax.persistence.*;
  
  @Entity
  @Table(name = "t_role")
  public class Role implements java.io.Serializable {
  
      /**
       * 
       */
      private static final long serialVersionUID = -7649041422061458221L;
  
      @Id
      @GeneratedValue(strategy = GenerationType.IDENTITY)
      @Column(name = "pk_role_id", unique = true, nullable = true)
      private Long roleID;
  
      @Column(name = "code", length = 45)
      private String code;
  
      @Column(name = "description", length = 45)
      private String description;
  
      @ManyToMany(mappedBy = "roles")
      private Set&lt;User&gt; users = new HashSet&lt;User&gt;();
  
      public Role () {
  
      }
  ...set,get...
  </code></pre>
  
  <p>test</p>
  
  <pre><code>    package demo.myssh.dao.impl;
  
      import org.hibernate.Session;
      import org.hibernate.SessionFactory;
      import org.junit.Test;
      import org.junit.runner.RunWith;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.beans.factory.annotation.Qualifier;
      import org.springframework.test.context.ContextConfiguration;
      import org.springframework.test.context.junit4.*;
      import org.springframework.transaction.annotation.Transactional;
      import demo.myssh.model.Role;
      import demo.myssh.model.User;
  
      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration({ "file:WebRoot/WEB-INF/applicationContext.xml" })
      public class hibernateTest {
          @Autowired
          @Qualifier("sessionFactory")
          private SessionFactory sessionFactory;
  
          private Session session;
  
          @Autowired
          @Qualifier("user")
          private User user;
  
          @Autowired
          @Qualifier("role")
          private Role role;
  
          @Test
          @Transactional
          public final void testHibernate() {
              session=sessionFactory.getCurrentSession();
  
              user.setEmail("aaf");
              role.setCode("ccf");
              user.getRoles().add(role);
              session.persist(user);
  
          }
      }
  </code></pre>
  
  <p>Console show</p>
  
  <pre><code>2012-12-18 22:39:05 Dialect [INFO] HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
  2012-12-18 22:39:05 LobCreatorBuilder [INFO] HHH000424: Disabling contextual LOB creation as createClob() method threw error : java.lang.reflect.InvocationTargetException
  2012-12-18 22:39:05 TransactionFactoryInitiator [INFO] HHH000399: Using default transaction strategy (direct JDBC transactions)
  2012-12-18 22:39:05 ASTQueryTranslatorFactory [INFO] HHH000397: Using ASTQueryTranslatorFactory
  2012-12-18 22:39:06 HibernateTransactionManager [INFO] Using DataSource [com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -&gt; 3, acquireRetryAttempts -&gt; 30, acquireRetryDelay -&gt; 1000, autoCommitOnClose -&gt; false, automaticTestTable -&gt; null, breakAfterAcquireFailure -&gt; false, checkoutTimeout -&gt; 0, connectionCustomizerClassName -&gt; null, connectionTesterClassName -&gt; com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -&gt; 1bqou1j8r1cekgod19q9xm8|26d58939, debugUnreturnedConnectionStackTraces -&gt; false, description -&gt; null, driverClass -&gt; com.mysql.jdbc.Driver, factoryClassLocation -&gt; null, forceIgnoreUnresolvedTransactions -&gt; false, identityToken -&gt; 1bqou1j8r1cekgod19q9xm8|26d58939, idleConnectionTestPeriod -&gt; 60, initialPoolSize -&gt; 3, jdbcUrl -&gt; jdbc:mysql://127.0.0.1:3306/myssh, lastAcquisitionFailureDefaultUser -&gt; null, maxAdministrativeTaskTime -&gt; 0, maxConnectionAge -&gt; 0, maxIdleTime -&gt; 10, maxIdleTimeExcessConnections -&gt; 0, maxPoolSize -&gt; 15, maxStatements -&gt; 0, maxStatementsPerConnection -&gt; 0, minPoolSize -&gt; 5, numHelperThreads -&gt; 3, numThreadsAwaitingCheckoutDefaultUser -&gt; 0, preferredTestQuery -&gt; null, properties -&gt; {user=******, password=******}, propertyCycle -&gt; 0, testConnectionOnCheckin -&gt; false, testConnectionOnCheckout -&gt; false, unreturnedConnectionTimeout -&gt; 0, usesTraditionalReflectiveProxies -&gt; false ]] of Hibernate SessionFactory for HibernateTransactionManager
  2012-12-18 22:39:06 Cglib2AopProxy [WARN] Unable to proxy method [public final void demo.myssh.dao.impl.hibernateTest.testHibernate()] because it is final: All calls to this method via a proxy will be routed directly to the proxy.
  2012-12-18 22:39:06 TransactionalTestExecutionListener [INFO] Began transaction (1): transaction manager [org.springframework.orm.hibernate4.HibernateTransactionManager@27af8502]; rollback [true]
  Hibernate: insert into t_user (email, login_name, ordercode, password) values (?, ?, ?, ?)
  Hibernate: insert into t_role (code, description) values (?, ?)
  2012-12-18 22:39:06 TransactionalTestExecutionListener [INFO] Rolled back transaction after test execution for test context [[TestContext@4d0ac2a3 testClass = hibernateTest, testInstance = demo.myssh.dao.impl.hibernateTest@7d7082d8, testMethod = testHibernate@hibernateTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@659e733e testClass = hibernateTest, locations = '{file:WebRoot/WEB-INF/applicationContext.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader']]]
  2012-12-18 22:39:06 GenericApplicationContext [INFO] Closing org.springframework.context.support.GenericApplicationContext@2acdb06e: startup date [Tue Dec 18 22:39:03 CST 2012]; root of context hierarchy
  2012-12-18 22:39:06 DefaultListableBeanFactory [INFO] Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@132789d2: defining beans  [dataSource,sessionFactory,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,transactionManager,user,message,role,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root  of factory hierarchy
  </code></pre>
  
  <p>It only saved entity,no saved relationship. The reason looks like </p>
  
  <pre><code>Cglib2AopProxy [WARN] Unable to proxy method [public final void demo.myssh.dao.impl.hibernateTest.testHibernate()] because it is final: All calls to this method via a proxy will be routed directly to the proxy.
  </code></pre>
  
  <p>but I'm not very clear,s o how should I do, please.</p>