软件世界网 购物 网址 三丰软件 | 小说 美女秀 图库大全 游戏 笑话 | 下载 开发知识库 新闻 开发 图片素材
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
移动开发 架构设计 编程语言 Web前端 互联网
开发杂谈 系统运维 研发管理 数据库 云计算 Android开发资料
  软件世界网 -> 架构设计 -> Hibernate4学习总结(2) -> 正文阅读

[架构设计]Hibernate4学习总结(2)


本文包括以下四个部分:
  1.  增删改查(CDUR)方法。
  2.  集合映射。
  3.  关联关系映射。
  4.  Inverse属性和cascade属性。

一、增删改查方法

需求:将客户对象保存进数据库。
User.java
package edu.scut.b_curd;
public class User {
	private int id;
	private String name;
	private String password;
	private String email;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", password=" + password
				+ ", email=" + email + "]";
	}
}
User表
[img]http://img.blog.csdn.net/20160331011239257?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
User.hbm.xml
<pre name="code" class="html"><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="edu.scut.b_curd.User" table="t_user">
		<!-- 主键 -->
		<id name="id" column="t_id">
			<generator class="assigned"></generator>
		</id>
		
		<!-- 普通属性 -->
		<property name="name" column="t_name" type="string" length="20"></property>
		<property name="password" column="t_password" length="20"></property>
		<property name="email" column="t_email" length="50"></property>
	</class>
</hibernate-mapping>





1.1 保存

在事务当中,如果发生异常,就需要回滚,将数据还原为之前的状态。

	public void test1(){
		//1 获取session对象
		Session session = HibernateUtil.getSession();
		
		//2 开启事务
		session.beginTransaction();
		
		try {
 			//3 保存user
			User user = new User();
 			user.setId(2);
			user.setName("张三丰");
			 user.setPassword("666666");
			user.setEmail("1156744308@qq.com");
			
			session.save(user);
			
			 //4 提交事务
			 session.getTransaction().commit();
		} catch (Exception e) {
 			e.printStackTrace();
 			//出现异常,回滚事务
			 session.getTransaction().rollback();
		} finally{
			 //关闭资源
			HibernateUtil.close(session);
		}
	}

1.2 更新

有两种方式,第一种方式需要对对象的每一项数据都要修改,否则将成为null;第二种只操作需要修改的属性,更为常用。

         public void test2(){
		//1 获取session对象
		Session session = HibernateUtil.getSession();
		//2 打开事务
		session.beginTransaction();
		
		try {
			//3 更新操作,有两种方式
			/*
			 * 第一种方式:
			 * <1>必须给id赋值;
			 * <2>hibernate会把所有字段都更新,如果对象的属性不赋值,则设置null
			 */
			/*User user = new User();
			user.setId(1);
			user.setName("荆天明");
			user.setPassword("666666");
			user.setEmail("1156744308@163.com");
			session.update(user);
			*/
			
			/*
			 * 第二种方式(推荐的方式)
			 * <1>先把需要更新的对象查询出来
			 * <2>参数一:查询的对象
			 * <3>参数二:ID值
			 */
			User user = (User) session.get(User.class,1);
			//修改需要更新的属性
			user.setName("盖聂");
			user.setPassword("88888888");
			
			//4 提交事务
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			//有异常,回滚事务
			session.getTransaction().rollback();
		} finally{
			//5 关闭资源
			HibernateUtil.close(session);
		}
	}

1.3 查询

较常用的是以下三种方式。

          public void test3(){
		//1 获取session对象
		Session session = HibernateUtil.getSession();
		//2 打开事务
		session.beginTransaction();
		
		try {
			//3 查询用户
			//<1>查询所有用户,hql
			Query query = session.createQuery("from User");
			List<User> users = query.list();
			for (User user : users) {
				System.out.println(user);
			}
			
			//<2>查询一个用户
			User user = (User) session.get(User.class,1);
			System.out.println(user);
			
			//<3>条件查询一个用户
			Query q = session.createQuery("select u from User u where name=? ");
			q.setParameter(0, "盖聂");
			User u = (User) q.uniqueResult();
			System.out.println(u);
			
			//4 提交事务
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			//有异常,回滚事务
			session.getTransaction().rollback();
		} finally{
			//5 关闭资源
			HibernateUtil.close(session);
		}
	}

1.4 删除

两种删除方式,推荐使用第一种。

           public void test4(){
		//1 获取session对象
		Session session = HibernateUtil.getSession();
		//2 打开事务
		session.beginTransaction();
		
		try {
			//3 删除用户
			//第一种,先查询出来
			User user = (User) session.get(User.class, 1);
			if(user!=null){
				session.delete(user);
			}
			
			//第二种(不推荐)
			User user2 = new User();
			user2.setId(2);
			session.delete(user2);
			
			//4 提交事务
			session.getTransaction().commit();
		} catch (Exception e) {
			e.printStackTrace();
			//有异常,回滚事务
			session.getTransaction().rollback();
		} finally{
			//5 关闭资源
			HibernateUtil.close(session);
		}	
	}

二、集合映射

需求:
客户购物时填写收货地址,收货地址是基本类型,而且有多个,这时应采用集合对地址进行封装。

1.1 Set集合
客户类属性:
       private int id;
       private String name;

       //使用Set集合来存储收货地址:元素无序的
       private Set<String> addressSet = new HashSet<String>();
User.hbm.xml
<!-- 映射set集合 
	name:Set集合的属性名称
	table:存储收货地址数据的表
	key:配置用户的外键
        -->
	<set name="addressSet" table="t_address">
		<!-- 外键 -->
		<key column="u_id"></key>
		<!-- Set元素的信息
			type:数据类型
			column:存放Set的数据字段名称
		 -->
		<element column="address_name" type="string"></element>
	</set>

1.2 List集合
客户类属性:
        private int id;
 	private String name;
        //使用List集合来存储收货地址:元素是有序的
        private List<String> addressList = new ArrayList<String>();
User.hbm.xml
<!-- 映射List集合 -->
	<list name="addressList" table="t_address_list">
		<!-- 外键 -->
		<key column="u_id"></key>
		<!-- list的索引字段(排序) -->
		<list-index column="idx"></list-index>
		<!-- list元素 -->
		<element column="address_name" type="string" ></element>
	</list>

1.3 Map集合
客户类属性
<pre name="code" class="html">        private int id;
	private String name;

//使用Map集合来存储收货地址:元素是无序的 private Map<String, String> addressMap = new HashMap<String, String>();

User.hbm.xml
<!-- 映射Map集合 -->
	<map name="addressMap" table="t_address_map">
		<!-- 外键 -->
		<key column="u_id"></key>
		<!-- key元素 -->
		<map-key type="string" column="address_no"></map-key>
		<!-- value元素 -->
		<element type="string" column="address_name"></element>
	</map>

三、关联关系映射

本文只对常用的集中映射关系做讲解。

一对多(单向)、多对一(单向)、一对多(双向)这三类映射采用客户(Customers)和订单(Orders)举例子,其中Customers是一方,Orders是多方。

3.1  多对一(单向)
a. 关系映射图解
[img]http://img.blog.csdn.net/20160331082949083?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
注意:多对一(单向)要在多方的属性当中加入一方,以此来建立单向关联。
本例中在多方实体类中添加:private Customers customers;
b. Customers.hbm.xml
<hibernate-mapping>
	<class name="edu.scut.a_many2one_single.Customers" table="t_customers">
		<id name="id" column="c_id">  
			<generator class="increment"></generator>
		</id>
		
		<property name="name" column="c_name"></property>
	</class>
</hibernate-mapping>

c. Orders.hbm.xml
<hibernate-mapping>
	<class name="edu.scut.a_many2one_single.Orders" table="t_orders">
		<id name="id" column="o_id">  
			<generator class="increment"></generator>
		</id>
		
		<property name="orderno" column="o_orderno"></property>
		
		<!-- 配置多对一的关系
		cascade:级联操作
			save-uodate:保存或者修改订单的同时,修改客户
			delete:删除订单的同时删除客户
			all:save+update+delete的功能之和
			none:默认,没有级联操作
		 -->
		<many-to-one name="customers" 
			column="c_id"
			class="edu.scut.a_many2one_single.Customers"
			cascade="all"></many-to-one>
	</class>
</hibernate-mapping>

d. 测试类(以save()方法为例)
建立了关系,并且配置了cascade,就可以实现级联操作。
         public void test1(){
		 //打开session
		 Session session = HibernateUtil.getSession();
		//打开事务
		s ession.beginTransaction();
		//添加用户
 		Customers customers = new Customers();
		customers.setName("东方朔");
 		//添加订单
		Orders o1 = new Orders();
 		o1.setOrderno("5166001");
		
 		Orders o2 = new Orders();
 		o2.setOrderno("5166002");
		
 		//建立关系(orders>>customers)
		o1.setCustomers(customers);
 		o2.setCustomers(customers);
		
		//保存数据
 		//如果采用了级联操作,直接保存订单,客户也可以保存
		//如果不配置相应的级联操作,那么会出现异常:(object references an unsaved transient instance - save the transient )
		 session.save(o1);
		session.save(o2);
		
		//提交事务
		session.getTransaction().commit();
		
		//关闭资源
                HibernateUtil.close(session);
 	}

3.2 一对多(单向)
a. 关系映射图解
[img]http://img.blog.csdn.net/20160331083728664?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
注意:一对多(单向)要在一方的属性当中加入集合来封装多方数据,以此来建立单向关联。
本例在一方实体类中添加:private Set<Orders> orders = new HashSet<Orders>();
b. Customers.hbm.xml
<hibernate-mapping>
	<class name="edu.scut.b_one2many_single.Customers" table="t_customers">
		<id name="id" column="c_id">  
			<generator class="increment"></generator>
		</id>
		
		<property name="name" column="c_name"></property>
		
		<!-- 配置一对多的关系
			name:属性名称
		 -->
		<set name="orders" cascade="all">
			 <!-- key:外键字段名称 -->
			 <key column="c_id"></key>
			 <!-- set集合的元素类型 -->
			 <one-to-many class="edu.scut.b_one2many_single.Orders"/>
		</set>
	</class>
</hibernate-mapping>

c. Orders.hbm.xml
<hibernate-mapping>
	<class name="edu.scut.b_one2many_single.Orders" table="t_orders">
		<id name="id" column="o_id">  
			<generator class="increment"></generator>
		</id>
		
		<property name="orderno" column="o_orderno"></property>
		
	</class>
</hibernate-mapping>

d. 测试类(以save()方法为例)
建立了关系,并且配置了cascade,就可以实现级联操作。
public void test1(){
		//打开session
		Session session = HibernateUtil.getSession();
		//打开事务
		session.beginTransaction();
		//添加用户
		Customers customers = new Customers();
		customers.setName("项羽");
		//添加订单
		Orders o1 = new Orders();
		o1.setOrderno("4326001");
		
		Orders o2 = new Orders();
		o2.setOrderno("5436002");
		
		//建立关系(customers>>orders)
		customers.getOrders().add(o1);
		customers.getOrders().add(o2);
		
		//保存数据
		session.save(customers);
		
		//提交事务
		session.getTransaction().commit();
		
		//关闭资源
		HibernateUtil.close(session);
	}

3.3 一对多/多对一(双向)

将一对多(单向)和多对一(单向)同时配置,并建立双向关系就是一会多(双向)。

注意:一对多(双向)要在一方的属性当中加入集合来封装多方数据,并在多方的属性当中加入一方的对象,以此来建立双向关联。
本例在一方实体类中添加:private Set<Orders> orders = new HashSet<Orders>();在多方实体类中添加:    private Customers customers;

a. Customers.hbm.xml
<hibernate-mapping>
	<class name="edu.scut.c_one2many_double.Customers" table="t_customers">
		<id name="id" column="c_id">  
			<generator class="increment"></generator>
		</id>
		
		<property name="name" column="c_name"></property>
		
		<!-- 配置一对多的关系
			name:属性名称
		 -->
 <p align="left">                <!-- inverse=true,如果出现在单方的话,表示由多方维护关系,默认是false,表示双方共同维护关系</p><p align="left">          如果双方共同维护关系的话,就会出现如下二种情况:</p><p align="left">          1)SQL多余了,但不出错 -》一对多双向关联</p><p align="left">          2)SQL多余了,但出错    -》多对多双向关联</p><p align="left">            --></p><p align="left"><span style="color:red;">               </span> <set name="orders" cascade="all" inverse="true">
</p>			 <!-- key:外键字段名称 -->
			 <key column="c_id"></key>
			 <!-- set集合的元素类型 -->
			 <one-to-many class="edu.scut.c_one2many_double.Orders"/>
 		</set>
	 </class>
</hibernate-mapping>

b. Orders.hbm.xml
<hibernate-mapping>
	<class name="edu.scut.c_one2many_double.Orders" table="t_orders">
		<id name="id" column="o_id">  
			<generator class="increment"></generator>
		</id>
		
		<property name="orderno" column="o_orderno"></property>
		
		<!-- 配置多对一的关系 -->
		<many-to-one name="customers"
			column="c_id"
			class="edu.scut.c_one2many_double.Customers"
			cascade="all"
		/>
	</class>
</hibernate-mapping>



d. 测试类(以save()方法为例)
建立了双向关系,并且配置了cascade,就可以实现级联操作。
public void test1(){
		//打开session
		Session session = HibernateUtil.getSession();
		//打开事务
		session.beginTransaction();
		//添加用户
		Customers customers = new Customers();
		customers.setName("项羽");
		//添加订单
		Orders o1 = new Orders();
		o1.setOrderno("4326001");
		
		Orders o2 = new Orders();
		o2.setOrderno("5436002");
		
		//建立双向关系
		//客户>>订单
		customers.getOrders().add(o1);
		customers.getOrders().add(o2);
		//订单>>客户
		o1.setCustomers(customers);
		o2.setCustomers(customers);
		
		//保存数据,保存客户和订单的任意一方,都可级联保存另一方
		session.save(customers);
		
		//提交事务
		session.getTransaction().commit();
		
		//关闭资源
		HibernateUtil.close(session);
	}

问题:有了一对多关联之后,保存数据时,会多余两条update语句!
解决方案:在一对多的关联关系配置中,在一方 把inverse="true"即可!
3.4 多对多(双向

多对多(双向)采用老师(Teacher)和学生(Student)举例子。

注意:多对多(双向)要在双方的实体类中同时加入集合封装对方的数据,以此来建立双向关联。多对多(双向)的关联中存在一个中间表,依赖中间表来建立两个表之间的关系。
本例在Student实体类中添加:private Set<Teachers> teachers = new HashSet<Teachers>();

在Teacher实体类中添加:   private Set<Students> students = new HashSet<Students>();

a. 关系映射图解
[img]http://img.blog.csdn.net/20160331083743461?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
b. Students.hbm.xml
<hibernate-mapping>
	<class name="edu.scut.d_many2many_double.Students" table="t_student">
		<id name="id" column="s_id">  
			<generator class="increment"></generator>
		</id>
		
		<property name="name" column="s_name"></property>
		
		<!-- 配置多对多的关系 
			 table:中间表的名称
		-->
		<set name="teachers" table="student_teacher" inverse="true">
			<!-- 当前对象所在中间表的外键 -->
			<key column="s_id"></key>
			<!-- set集合的元素类型 -->
			<!-- column:集合类型所在中间表的外键 -->
			<many-to-many class="edu.scut.d_many2many_double.Teachers" column="t_id"></many-to-many>
		</set>
	</class>
</hibernate-mapping>

c. Teachers.hbm.xml
<hibernate-mapping>
	<class name="edu.scut.d_many2many_double.Teachers" table="t_teacher">
		<id name="id" column="t_id">  
			<generator class="increment"></generator>
		</id>
		
		<property name="name" column="t_name"></property>
		
		<!-- 配置多对一的关系 -->
		<set name="students" table="student_teacher" cascade="all">
			<!-- 当前对象所在中间表的外键 -->
			<key column="t_id"></key>
			<!-- set集合类型 -->
			<!-- column:集合类型所在中间表的外键 -->
			<many-to-many class="edu.scut.d_many2many_double.Students" column="s_id"></many-to-many>
		</set>
	</class>
</hibernate-mapping>

d. 测试类(以save()方法为例)
建立了双向关系,并且配置了cascade,就可以实现级联操作。

public void test1(){
		//打开session
		Session session = HibernateUtil.getSession();
		//打开事务
		session.beginTransaction();
		
		//保存学生
		Students s1 = new Students();
		s1.setName("小强");
		Students s2 = new Students();
		s2.setName("小花");
		
		//保存老师
		Teachers t1 = new Teachers();
		t1.setName("李老师");
		Teachers t2 = new Teachers();
		t2.setName("卢老师");
		
		//建立双向关系
		//学生>>老师
		s1.getTeachers().add(t1);
		s1.getTeachers().add(t2);
		s2.getTeachers().add(t1);
		s2.getTeachers().add(t2);
		
		//老师>>学生
		t1.getStudents().add(s1);
		t1.getStudents().add(s2);
		t2.getStudents().add(s1);
		t2.getStudents().add(s2);
		
		//保存数据,保存客户和订单的任意一方,都可级联保存另一方
		session.save(t1);
		session.save(t2);
		
		//提交事务
		session.getTransaction().commit();
		
		//关闭资源
		HibernateUtil.close(session);
	}

问题:在多对多双向关联中,SQL多余了,而且报错

解决方案:在任的多方把inverse="true"即可!
3.5 一对一(双向

一对一(双向)采用公民和身份证举例子。

注意:一对一(双向)要在双方的实体类中同时加入对方的对象,以此来建立双向关联。
本例在Personst实体类中添加:private IdCards idcards;
在IdCards实体类中添加:   private Persons persons;

a. 关系映射图解
[img]http://img.blog.csdn.net/20160331083800695?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
b. IdCards.hnm.xml
有两种方式建立一对一(双向)的关系。
<hibernate-mapping>
	<class name="edu.scut.e_one2one_double.IdCards" table="t_idcards">
		<id name="id" column="i_id">  
			<generator class="increment"></generator>
		</id>
		
		<property name="cardno" column="i_cardno"></property>
		
		<!-- 一对一配置方式有两种 -->
		<!-- 第一种:唯一外键
			是一种特殊的多选一方式,但是外键多了unique约束
		 -->
		<!-- <many-to-one name="persons"
			class="edu.scut.e_one2one_double.Persons"
			column="p_id"
			unique="true">
		</many-to-one> -->
		
		<!-- 第二种:主键关联
			constrained:是否把主键作为外键
			false:不作为外键
			true:作为外键
		-->
		<one-to-one name="persons"
			class="edu.scut.e_one2one_double.Persons"
			constrained="true">
		</one-to-one>
	</class>
</hibernate-mapping>

c. Persons.hbm.xml
<hibernate-mapping>
	<class name="edu.scut.e_one2one_double.Persons" table="t_persons">
		<id name="id" column="p_id">  
			<generator class="increment"></generator>
		</id>
		
		<property name="name" column="p_name"></property>
		
		<!-- 配置一对一的关系 -->
		<one-to-one name="idcards"
			class="edu.scut.e_one2one_double.IdCards"
			cascade="all">
		</one-to-one>
	</class>
</hibernate-mapping>

d. 测试类(以save()方法为例)
建立了双向关系,并且配置了cascade,就可以实现级联操作。
public void test1(){
		//打开session
		Session session = HibernateUtil.getSession();
		//打开事务
		session.beginTransaction();
		
		//公民
		Persons p = new Persons();
		p.setName("杨过");
		
		//身份证
		IdCards ic = new IdCards();
		ic.setCardno("6104271990");
		
		//建立关系
		//公民>>身份证
		p.setIdcards(ic);
		
		//身份证>>公民
		ic.setPersons(p);
	
		//保存数据
		session.save(p);
		
		//提交事务
		session.getTransaction().commit();
		
		//关闭资源
		HibernateUtil.close(session);
	}

四、Inverse属性和cascade属性

4.1 Inverse属性
                 Inverse属性是在维护关联关系的时候起作用的,表示控制权是否转移。
                 Inverse= false  不反转;   当前方有控制权。
                 Inverse= True  控制反转; 当前方没有控制权。
                 默认是   Inverse= false,在一对多(双向)和多对多(双向)的关联关系中,如果不明确配置,则默认Inverse= false,即两边都具有控制权,在执行保存操作的时候,双方能否会维护表。导致一对多(双向)的关联关系出现出现多余的SQL语句,而多对多(双向)关联中直接报错(org.hibernate.exception.ConstraintViolationException:could not execute statement, Caused by:com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:Duplicate entry '7-7' for key 'PRIMARY'),提示中间表有重复的主键。因此,需要自己手动配置Inverse=“true”。
4.2 cascade属性
cascade 表示级联操作(可以设置到一的一方或多的一方)
  • none:不级联操作, 默认值。
  • save-update:级联保存或更新。
  • delete:级联删除。
  • save-update,delete:级联保存、更新、删除。
  • all:同上。级联保存、更新、删除。

             
       
        
        
       
......显示全文...
    点击查看全文


上一篇文章      下一篇文章      查看所有文章
2016-04-01 16:50:07  
架构设计 最新文章
Opengl教程之读取obj并绘制在picturecontro
读《企业应用架构模式》第五章并发
StepbyStepintoSpring(IOC)
设计模式(2)用例图之一
使用实体组件系统(ECS)开发”吃方块”游戏实
编程学习之简单工厂模式与策略模式
Invalidprojectdescription.
基于Redis实现分布式消息队列(2)
《开源框架那点事儿15》:借船下海还是造船
原型模式——浅复制和深复制
360图书馆 软件开发资料 文字转语音 购物精选 软件下载 美食菜谱 新闻资讯 电影视频 小游戏 Chinese Culture 股票 租车
生肖星座 三丰软件 视频 开发 短信 中国文化 网文精选 搜图网 美图 阅读网 多播 租车 短信 看图 日历 万年历 2018年1日历
2018-1-16 21:18:38
多播视频美女直播
↓电视,电影,美女直播,迅雷资源↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件世界网 --