我正在学习休眠,但我无法保存多对多关系。我使用休眠 4.1.8 和弹簧 3.1.3
表
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
应用程序上下文.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/myssh" />
<property name="user" value="root" />
<property name="password" value="" />
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="15" />
<property name="initialPoolSize" value="3" />
<property name="maxIdleTime" value="10" />
<property name="acquireIncrement" value="3" />
<property name="maxStatements" value="0" />
<property name="idleConnectionTestPeriod" value="60" />
<property name="acquireRetryAttempts" value="30" />
<property name="breakAfterAcquireFailure" value="false" />
<property name="testConnectionOnCheckout" value="false" />
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="annotatedClasses">
<list>
<value>demo.myssh.model.User</value>
<value>demo.myssh.model.Role</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">false</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.autoReconnect">true</prop>
<prop key="hibernate.max_fech_depth">5</prop>
<prop key="hibernate.jdbc.batch_size">50</prop>
<prop key="hibernate.jdbc.fetch_size">100</prop>
<prop key="javax.persistence.validation.mode">none</prop>
<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate4.SpringSessionContext
</prop>
</props>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="user" class="demo.myssh.model.User"></bean>
<bean id="message" class="demo.myssh.model.Message"></bean>
<bean id="role" class="demo.myssh.model.Role"></bean>
</beans>
用户
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<Role> roles = new HashSet<Role>();
public User() {
}
...set,get...
角色
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<User> users = new HashSet<User>();
public Role () {
}
...set,get...
测试
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);
}
}
控制台展示
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 -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, dataSourceName -> 1bqou1j8r1cekgod19q9xm8|26d58939, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, identityToken -> 1bqou1j8r1cekgod19q9xm8|26d58939, idleConnectionTestPeriod -> 60, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://127.0.0.1:3306/myssh, lastAcquisitionFailureDefaultUser -> null, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 10, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 5, numHelperThreads -> 3, numThreadsAwaitingCheckoutDefaultUser -> 0, preferredTestQuery -> null, properties -> {user=******, password=******}, propertyCycle -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, usesTraditionalReflectiveProxies -> 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
它只保存实体,没有保存关系。原因看起来像
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.
但是我不是很清楚,请问我该怎么做。