映射关系包含四种
①一对多 one-to-many
②多对一 many-to-one
③一对一 one-to-one
④多对多 many-to-many
这个里面还区别单向和双向
单向一对多映射
实现核心:在one方持有many方的集合
一个班级包含多个学生,在班级中添加学生的集合List集/Set集
班级是一方,学生是多方
下面以http://sunyuqian.iteye.com/blog/2248913中实例为基础来实现一个单向一对多实例
1.hibernate.cfg.xml
在基础(一)的blog中已经对各个属性进行了说明,在此不赘述。
注意一点是:使用到了getCurrentSession(),所以添加了"hibernate.current_session_context_class"配置
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- oracle数据库驱动 --> <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <!-- oracle想要连接的数据库名称 --> <property name="connection.url">jdbc:oracle:thin:@10.1.0.169:1521:orcl</property> <!-- 数据库的登陆用户名 --> <property name="connection.username">SUNYQ</property> <!-- 数据库的登陆密码 --> <property name="connection.password">123456</property> <!-- 方言:为每一种数据库提供适配器,方便转换 --> <property name="hibernate.dialect">org.hibernate.dialect.Oracle9iDialect</property> <property name="show_sql">true</property> <property name="format_sql">true</property> <property name="hibernate.current_session_context_class">thread</property> <property name="hbm2ddl">create</property> <mapping resource="Students.hbm.xml"/> <mapping resource="Grade.hbm.xml"></mapping> </session-factory> </hibernate-configuration>
2.创建持久化实体类
也可在数据库中事先创建出来学生表和班级表,也可以通过配置文件来设置,方式根据需求来定,本文使用配置文件来生成数据库表。
Students类:
package com.iteye.sunyq.hibernate; public class Students { public Students() { } private int sid; private String sname; public int getSid() { return sid; } public void setSid(int sid) { this.sid = sid; } public String getSname() { return sname; } public void setSname(String sname) { this.sname = sname; } public Students(String sname) { super(); this.sname = sname; } }
Grade类
package com.iteye.sunyq.hibernate; import java.util.HashSet; import java.util.Set; public class Grade { public Grade(){ } private int gid; private String gname; private String gdesc; private Set<Students> studentSet = new HashSet<Students>(); public int getGid() { return gid; } public void setGid(int gid) { this.gid = gid; } public String getGname() { return gname; } public void setGname(String gname) { this.gname = gname; } public String getGdesc() { return gdesc; } public void setGdesc(String gdesc) { this.gdesc = gdesc; } public Set<Students> getStudentSet() { return studentSet; } public void setStudentSet(Set<Students> studentSet) { this.studentSet = studentSet; } public Grade(String gname, String gdesc) { super(); this.gname = gname; this.gdesc = gdesc; } }
注意:根据一对多映射关系的实现原理-》是在一方持有多方的集合,也就是在Grade.java中包含Students.java的集合。
private Set<Students> studentSet = new HashSet<Students>();
那么通过这种方式生成的表结构是什么样的呢?提前看一下
grade表:
students表:
students表中外键gid:
所以,通过持久化类中包含students集合实际就是students表与grade表gid进行了外键的关联
3.映射文件
Students.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.iteye.sunyq.hibernate.Students" table="students"> <id name="sid" type="integer"> <column name="id"></column> <generator class="native"></generator> </id> <property name="sname" type="string"> <column name="sname"></column> </property> </class> </hibernate-mapping>
Grade.hbm.xml
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="com.iteye.sunyq.hibernate.Grade" table="grade"> <id name="gid" type="integer"> <column name="id"></column> <generator class="native"></generator> </id> <property name="gname" type="string"> <column name="gname"></column> </property> <property name="gdesc" > <column name="gdesc"></column> </property> <set name="studentSet"> <key column="gid"/> <one-to-many class="com.iteye.sunyq.hibernate.Students"></one-to-many> </set> </class> </hibernate-mapping>
注意:
①首先在Students表中的外键gid是不需要写到Students.hbm.xml中的,这个外键是在一方进行维护,就是Grade.hbm.xml中进行维护
②Grade.hbm.xml中外键gid是写在<set>标签中的
<set name="studentSet"> <key column="gid"/><!-- Students表中外鍵名称 --> <one-to-many class="com.iteye.sunyq.hibernate.Students"></one-to-many><!-- 映射的实体类 --> </set>
4.Hibernate工具类
对Hibernate的链接数据库抽象到一个工具类中
package com.iteye.sunyq.hibernate; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class HibernateUtil { private static SessionFactory sessionFactory; private static Session session; static{ Configuration config = new Configuration().configure(); ServiceRegistry service = new StandardServiceRegistryBuilder().applySettings(config.getProperties()).build(); sessionFactory = config.buildSessionFactory(service); } public static SessionFactory getSessionFactory(){ return sessionFactory; } public static Session getSession(){ session = sessionFactory.openSession(); return session; } public static void closeSession(Session session){ if(session != null) session.close(); } }
5.测试:增删改查
注意:通过配置文件建立关联关系之后,可以比较方便的根据一来导航到多的对象
但是,反过来是不可以的,因为是单向的。也就是说可以通过班级来对学生进行一定的操作,而是用学生却不能对班级进行相应的操作。
举例:可以通过班级来查询到该班级下的所有学生对象的信息,而只去查询学生,并不能查询到班级对象的信息。
package com.iteye.sunyq.hibernate; import java.util.Set; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; public class Test { public static void main(String[] args) { addStudent(); findStudent(); deleteStudent(); update(); } public static void addStudent(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Grade grade = new Grade("班级二","班级二描述"); Students student1 = new Students("王五"); grade.getStudentSet().add(student1); session.save(grade); session.save(student1); transaction.commit(); HibernateUtil.closeSession(session); } public static void findStudent(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Grade grade = (Grade) session.get(Grade.class, 1); System.out.println("班级:"+grade.getGid()+","+grade.getGname()+","+grade.getGdesc()); Set<Students> students = grade.getStudentSet(); for(Students info : students){ System.out.println("学生:"+info.getSid()+""+info.getSname()); } //注意:因为是单向映射,我们不能通过student的信息来获取到grade信息。 Students s = (Students)session.get(Students.class, 2); System.out.println("查询学生信息:"+s.getSid()+"-"+s.getSname()); transaction.commit(); HibernateUtil.closeSession(session); } public static void deleteStudent(){ SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.getCurrentSession(); Transaction transaction = session.beginTransaction(); Students student = (Students)session.get(Students.class, 9); session.delete(student); transaction.commit(); } public static void update(){ Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Grade grade = (Grade) session.get(Grade.class, 8); Students student = (Students) session.get(Students.class, 9); student.setSname("哈哈"); grade.getStudentSet().add(student); session.save(grade); transaction.commit(); HibernateUtil.closeSession(session); } }