一、班级学生一对多映射实现(单向)
Class 1 * Student 一对多
在学生多的一方,配置一的对象;
com.cy.model.Class:
package com.cy.model; public class Class { private long id; private String name; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
com.cy.model.Student:
package com.cy.model; public class Student { private long id; private String name; private Class c; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Class getC() { return c; } public void setC(Class c) { this.c = c; } @Override public String toString() { return "Student [id=" + id + ", name=" + name + "]"; } }
Class.hbm.xml:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.cy.model"> <class name="Class" table="t_class"> <id name="id" column="classId"> <generator class="identity"></generator> </id> <property name="name" column="className"></property> </class> </hibernate-mapping>
Student.hbm.xml:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.cy.model"> <class name="Student" table="t_student"> <id name="id" column="stuId"> <generator class="identity"></generator> </id> <property name="name" column="stuName"></property> <!-- 属性名是c; 表的外键的列名是classId,关联类com.cy.model.Class --> <many-to-one name="c" column="classId" class="com.cy.model.Class"></many-to-one> </class> </hibernate-mapping>
hibernate.cfg.xml:
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!--数据库连接设置 --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property> <property name="connection.username">root</property> <property name="connection.password">root</property> <!-- 方言 --> <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- 控制台显示SQL --> <property name="show_sql">true</property> <!-- 自动更新表结构 --> <property name="hbm2ddl.auto">update</property> <mapping resource="com/cy/model/Student.hbm.xml"/> <mapping resource="com/cy/model/Class.hbm.xml"/> </session-factory> </hibernate-configuration>
测试程序:
public class StudentTest { public static void main(String[] args) { SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.openSession(); session.beginTransaction(); Class c = new Class(); c.setName("08计本"); session.save(c); Student s1 = new Student(); s1.setName("张三"); s1.setC(c); Student s2 = new Student(); s2.setName("李四"); s2.setC(c); session.save(s1); session.save(s2); session.getTransaction().commit(); session.close(); } }
运行之后可以看到建表情况和数据插入情况:
Class表:
Student表:
外键关系:
数据插入成功;
二、Junit4 方法详解
下面是测试代码,验证这一过程:
package com.cy.service; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class StudentTest2 { @BeforeClass public static void setUpBeforeClass() throws Exception { System.out.println("类初始化前调用..."); } @AfterClass public static void tearDownAfterClass() throws Exception { System.out.println("类初始化后调用..."); } @Before public void setUp() throws Exception { System.out.println("测试方法前调用..."); } @After public void tearDown() throws Exception { System.out.println("测试方法后调用..."); } @Test public void test() { System.out.println("测试方法..."); } /* * 打印如下: 类初始化前调用... 测试方法前调用... 测试方法... 测试方法后调用... 类初始化后调用... */ }
三、级联保存更新
比如新建了Class班级,但是没有保存它,但是新建两个Student,引用这个Class,保存这两个Student,观察:
StudentTest3.java:
package com.cy.service; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.cy.model.Class; import com.cy.model.Student; import com.cy.util.HibernateUtil; public class StudentTest3 { private SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); private Session session; @Before public void setUp() throws Exception { session = sessionFactory.openSession(); session.beginTransaction(); } @After public void tearDown() throws Exception { session.getTransaction().commit(); session.close(); } @Test public void testSaveClassAndStudentWithCascade() { Class c = new Class(); //临时对象,还没有被持久化 c.setName("08计本"); Student s1 = new Student(); s1.setName("张三"); s1.setC(c); Student s2 = new Student(); s2.setName("李四"); s2.setC(c); session.save(s1); //(cascade为none) student持久化对象引用了一个临时对象,保存抛出异常,保存失败。 session.save(s2); } }
运行testSaveClassAndStudentWithCascade,发现保存失败:
于是我们修改Student.hbm.xml中的配置:
<hibernate-mapping package="com.cy.model"> <class name="Student" table="t_student"> <id name="id" column="stuId"> <generator class="identity"></generator> </id> <property name="name" column="stuName"></property> <!-- 属性名是c; 表的外键的列名是classId,关联类com.cy.model.Class --> <many-to-one name="c" column="classId" class="com.cy.model.Class" cascade="save-update"></many-to-one> </class> </hibernate-mapping>
再次运行testSaveClassAndStudentWithCascade,级联保存成功!!