Hibernate映射之一对多映射(三)

前面已经对Hibernate有了基本的了解,下面说一下Hibernate的各种映射
映射关系包含四种
①一对多 one-to-many
②多对一 many-to-one
③一对一 one-to-one
④多对多 many-to-many
这个里面还区别单向和双向

单向一对多映射
实现核心:在one方持有many方的集合
一个班级包含多个学生,在班级中添加学生的集合List集/Set集
班级是一方,学生是多方
下面以http://sunyuqian.iteye.com/blog/2248913中实例为基础来实现一个单向一对多实例

Hibernate映射之一对多映射(三)_第1张图片

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表:
Hibernate映射之一对多映射(三)_第2张图片
students表:
Hibernate映射之一对多映射(三)_第3张图片
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);
	}
}


你可能感兴趣的:(java,Hibernate)