Hibernate(三)

 

 

目录

缓存

拦截器:

生成器类:

事务

关系映射模型:

关联级别策略


 

缓存

缓存是关于应用程序性能的优化,降低了应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。

​ <cache usage="read-write"/>参数告诉hibernate使用read-write并发策略缓存对 Hibernate 来说也是重要的,它使用了如下解释的多级缓存方案:

一级缓存

第一级缓存是 Session 缓存并且是一种强制性的缓存,所有的要求都必须通过它。Session 对象在它自己的权利之下,在将它提交给数据库之前保存一个对象。

如果你对一个对象发出多个更新,Hibernate 会尝试尽可能长地延迟更新来减少发出的 SQL 更新语句的数目。如果你关闭 session,所有缓存的对象丢失,或是存留,或是在数据库中被更新。提高查询状态,减少不必要的修改语句的发送

二级缓存

​ 第二级缓存是一种可选择的缓存并且第一级缓存在任何想要在第二级缓存中找到一个对象前将总是被询问。第二级缓存可以在每一个类和每一个集合的基础上被安装,并且它主要负责跨会话缓存对象。任何第三方缓存可以和 Hibernate 一起使用。org.hibernate.cache.CacheProvider 接口被提供,它必须实现来给 Hibernate 提供一个缓存实现的解决方法。

查询层次缓存

​ Hibernate 也实现了一个和第二级缓存密切集成的查询结果集缓存。这是一个可选择的特点并且需要两个额外的物理缓存区域,它们保存着缓存的查询结果和表单上一次更新时的时间戳。这仅对以同一个参数频繁运行的查询来说是有用的。

​ 第二级缓存

​ Hibernate 使用默认的一级缓存并且你不用使用一级缓存。让我们直接看向可选的二级缓存。不是所有的类从缓存中获益,所以能关闭二级缓存是重要的。

​ Hibernate 的二级缓存通过两步设置。第一,你必须决定好使用哪个并发策略。之后,你使用缓存提供程序来配置缓存到期时间和物理缓存属性。

并发策略

​ 一个并发策略是一个中介,它负责保存缓存中的数据项和从缓存中检索它们。如果你将使用一个二级缓存,你必须决定,对于每一个持久类和集合,使用哪一个并发策略。

​ Transactional:为主读数据使用这个策略,在一次更新的罕见状况下并发事务阻止过期数据是关键的。​ Read-write:为主读数据再一次使用这个策略,在一次更新的罕见状况下并发事务阻止过期数据是关键的。​ Nonstrict-read-write:这个策略不保证缓存和数据库之间的一致性。如果数据几乎不改变并且过期数据不是很重要,使用这个策略。​ Read-only:一个适合永不改变数据的并发策略。只为参考数据使用它。

查询层次缓存

​ 为了使用查询缓存,你必须首先使用配置文件中的 hibernate.cache.use_query_cache="true" 属性激活它。通过设置这个属性为真,你使得 Hibernate 创建内存中必要的缓存来保存查询和标识符集。

​ 然后,为了使用查询缓存,你使用 Query 类的 setCacheable(Boolean) 方法。例如:

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
List users = query.list();
SessionFactory.closeSession();

​ Hibernate 通过缓存区域的概念也支持非常细粒度的缓存支持。一个缓存区域是被给予名字的缓存部分。

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
query.setCacheRegion("employee");
List users = query.list();
SessionFactory.closeSession();		

拦截器:

​ 在 Hibernate 中,一个对象将被创建和保持。一旦对象已经被修改,它必须被保存到数据库里。这个过程持续直到下一次对象被需要,它将被从持久的存储中加载。

​ 因此一个对象通过它生命周期中的不同阶段,并且 Interceptor 接口提供了在不同阶段能被调用来进行一些所需要的任务的方法。

​ 这些方法是从会话到应用程序的回调函数,允许应用程序检查或操作一个持续对象的属性,在它被保存,更新,删除或上传之前​

生成器类:

​ 所有的生成器类都实现IDentifierGenerator接口,可通过实现接口创建自己的生成器类:​ 主键策略:

<id name="cust_id" column="cust_id">
  <!-- 生成主键策略
  主键的生成规则:
  identity :主键自增,录入是不需要指定id的
  increate:主键自增,由hinbernate维护,每次会查询id最大值,然后另其+1(勿用线程安全问题)
  sequence:oracle主键生成策略
  hilo:一种主键自增的策略;高低算法,由hinbernate维护 (不需要用)
  native:hilo+sequence+identity自动三选一,有配置文件筛选出来;
  uuid:string类型的主键,产生随机数id
  assigned:自然生成,有开发人员维护主键
  -->
  <generator class="native"></generator>
</id>
assigned:
  <generator>元素,assigned是默认的生成器策略。在这种情况下,应用程序为对象分配ID
  <hibernate-mapping>
  <class ...>
  <id ...>
  <generator class="assigned"></generator>
  </id>
  .....
  </class>
</hibernate-mapping>

increment

​ 当没有其他进程将数据插入此表时,才会生成唯一的ID。 它生成short,int或long型标识符。 第一个生成的标识符通常为1,然后每次递增为1​ <generator class="increment"></generator>

​sequence

​ 它使用数据库的顺序序列。如果没有定义序列,它会自动创建一个序列。 在Oracle数据库的情况下,它将创建一个名为HIBERNATE_SEQUENCE的序列。

​ 在Oracle,DB2,SAP DB,Postgre SQL或McKoi的情况下,它使用序列(sequence),但在interbase中使用生成器可以定义自己的序列​ <id ...> ​ <generator class="sequence"> ​ <param name="sequence">your_sequence_name</param> ​ </generator> ​ </id>​ hilo:它使用高低算法来生成short,int和long类型的id

​ native:它使用标识,序列或希洛取决于数据库供应商

​ identity 用于Sybase,Mysql,MS SQL Server,DB2和Hypersonic SQL以支持id列。 返回的ID类型为short,int或long

​ ......​ ....

对象状态:

​ 瞬时状态:

​ new

​ 持久化状态:​ save只是把瞬时状态变为持久状态;

​ 托管状态:​ close

​ 作用:将希望同步导数据库中的数据对象,转化为持久化数据

​ 持久化---》delete-->瞬时状态

​ 托管---》update--->持久化状态

​ 瞬时---》save---->持久化状态

事务

​ 在项目中如何管理事务:

​ 业务开始之前打开事务,业务执行之后提交事务,执行过程出现异常回滚事务,在dao层操作数据库需要用到session对象,在service控制事务也是使用session对象完成,要确保dao层,和service层用的是同一个session队形

​ 当时通过:connection由service层----》dao层同时传递connection对象

​ hibernate中确保使用的是同一个session对象 只需要用SesssionFactroy调用 getCurrentSession()的的方法即可以得到与当前线程绑定的对象

​ 调用时:必须配合主配置的文件:指定当前线程与session绑定​<property name="current_session_context_class">thread</proterty>

​ 这个session对象当事务提交时会自动关闭session,自己不需要手动关闭

关系映射模型:

​ 数据模型:是对数据的库特征的抽象的,用户从数据库中看到的模型,主要有DBMS实现

​ 领域模型:是对现实世界的对象的可视化表现主要是现实世界与计算机之间的一条纽带。

一对一主键关联:

​ 例如居民和身份证

​ user{​ id,name,sex,age​ }​ card{​ id,IDCode​ }​ 配置形式:

user:
<one-to-one name="com.leo.IDcode" cascade="all">//配置级联操作
card:
<one-to-one name="com.leo.People" constrained="true">//constrained="true"是,constrained只能在one-to-one的映射中使用,(一般在主表的映射中,有外键的那个表)

一对一外键关联:

​ user{​ id,name,sex,age,card_id​ }​ card{​ id,IDCode​ }

user.hbm.xml:
<many-to-one name="icard" column="card_id" unique="true" >
</many-to-one>
card.hbm.xml:
需要配置外键在主键配置策略中:
<id name="" cloumn=" " type="">
    <generator class="foreign">
        <param name="property">people</param>
    </generator>
</id>

一对多:

一的一方:

<!-- 集合一对多 -->
<!--name:集合的属性名,class:与外键关联的完整的类名 ,column:是哪个列为外键  -->
<!--级联操作:cascade=""  save-update:级联保存更新,delete:级联删除,all:级联删除和保存
操作性质:是数据的操作的简化
-->
<!-- inverse属性:配置关系是否维护 ,true:是让对方维护这个关系
false:是双方都会维护的
如果不配置是双方都会维护的
原则:总有一方要维护关系
只能是一的一方放弃维护关系,多的一方必须维护
-->
<set name="linkMens" inverse="true">
	<key column="lkm_cust_id"/>
	<one-to-many class="LinkMan"/>
</set>

多的一方:

<!-- 
fetch 决定加载的sql语句
select: 使用单表查询
join : 多表查询
lazy  决定加载时机
false: 立即加载
proxy: 由customer的类级别加载策略决定.
-->
<!--级联操作:cascade=""  save-update:级联保存更新,delete:级联删除,all:级联删除和保存
操作性质:是数据的操作的简化
多对一的单向的操作,需要在持久化得类的外键中引入另一个表中的主键,
这是使用的是双向关联
-->
<!-- 在多的一方是不能够放弃维护关系的,外键字段是多的一方的列 -->	 
<many-to-one name="customer" column="lkm_cust_id" class="Customer" fetch="join" lazy="proxy"  >
</many-to-one>

级联删除:
//删除的时候需要用级联删除,如果要删除可以用:inverse="false";这是维护外键,可以直接删并设置外键为空
//或者用 不维护外键:inverse="true",casecade="delete";级联删除;
//3操作
//1> 获得要操作的客户对象

Customer c = session.get(Customer.class,5l);
session.delete(c);

多对多:

​ 员工----角色:​ 多对多的一般引入第三个表用来保存员工和角色的主键用来维护两个表的关系

​ 其实就是在第三个表去维护两个主键来达到多对多的关系​

实体表的使用:
	User{
		id,name,Set<roel> role
	}
	role{
		id,name,Set<User>  user
	}

`
设置User.hcm.xml
		///省略;;; 
		<set name="role" table="tab_mapping">
			<key clomu="user_id"></key>
			<many-to-many class="com.leo.Role" column="role_id"/>
		</set>
设置role.hcm.xml
		<set name="user" table="tab_mapping">
			<key column="role_id"></key>
			<many-to-many class="com.leo.User" column="user_id"/>
		</set>
用户---角色
		//保存员工以及角色
public void fun1() {
        //1 获得session
        Session session = HibernateUtil.openSession();
        //2 开启事务
        Transaction tx = session.beginTransaction();
        //-------------------------------------------------
        //3操作
        //1> 创建两个 User
        User u1 = new User();
        User u2 = new User();
        u1.setUser_name("张三");
        u2.setUser_name("李四");
        //2> 创建两个 Role
        Role r1 = new Role();
        Role r2 = new Role();
        r1.setRole_name("保洁");
        r2.setRole_name("保安");
        //3> 用户表达关系
        u1.getRoles().add(r1);
        u1.getRoles().add(r2);

        u2.getRoles().add(r1);
        u2.getRoles().add(r2);
        //如果不配置的时候 两个都会进行关系维户,会进行主键约束重复不可以用
        //inverse="true" 属性在另一方维护关系,这个放弃维护关系
        //4> 角色表达关系
        r1.getUsers().add(u1);
        r1.getUsers().add(u2);

        r2.getUsers().add(u1);
        r2.getUsers().add(u2);

        //5> 调用Save方法一次保存
        session.save(u1);
        session.save(u2);
        session.save(r1);
        session.save(r2);
        //-------------------------------------------------
        //4提交事务
        tx.commit();
        //5关闭资源
        session.close();
    }
设置User.hcm.xml:
<!-- 多对多关系表达 -->
  <!-- 
   name: 集合属性名对应的是实例类的属性值
   table: 配置中间表名
   key
    |-column:外键,别人引用"我"的外键列名,即第三方表中引用我的主键
    class: 我与哪个类是多对多关系
    column:外键.我引用比人的外键列名
    <many-to-many> 配置的是这个表中的另一个外键
   -->
<!-- 这个就是简化了save语句:
   cascade级联操作:
     save-update: 级联保存更新
     delete:级联删除
     all:级联保存更新+级联删除
   结论: cascade简化代码书写.该属性使不使用无所谓. 建议要用只用save-update.
     如果使用delete操作太过危险.尤其在多对多中.不建议使用. 一般不用。
-->
<set name="roles" table="sys_user_role" cascade="save-update" >
	<key column="user_id" ></key>
	<many-to-many class="Role" column="role_id" ></many-to-many>
</set>
设置role.hbm.xml
<!-- 使用inverse属性
     true: 放弃维护外键关系
     false(默认值):维护关系
     many-to-many是配置的另一个的关系的列和对应的类
    结论: 将来在开发中,如果遇到多对多关系.一定要选择一方放弃维护关系.
      一般谁来放弃要看业务方向. 例如录入员工时,需要为员工指定所属角色.
      那么业务方向就是由员工维护角色. 角色不需要维护与员工关系.角色放弃维护
-->		
<set name="users" table="sys_user_role" inverse="true" >
  <key column="role_id" ></key>
  <many-to-many class="User" column="user_id" ></many-to-many>
</set>

关联级别策略

级联操作: 数据库中利用主外键约束保护数据的一致性,级联是指当主控方执行save,update,delete时,进行的同步操作,

​ 在映射文件中通过cascade属性设置关联对象的级联操作,cascade="" save-update:级联保存更新,delete:级联删除,all:级联删除和保存

​ 操作性质:是数据的操作的简化

​ 级联操作关系维护:inverse属性:配置关系是否维护 ,true:是让对方维护这个关系

​ false:是双方都会维护的

​ 如果不配置是双方都会维护的

​ 原则:总有一方要维护关系

​ 只能是一的一方放弃维护关系,多的一方必须维护

<hibernate-mapping package="com.leo.domain">
    <class name="Customer" table="cust_customer">
	<!-- id映射主键属性name:填对应的属性名,column列名 -->
		<id name="cust_id" column="cust_id">
			<generator class="identity"></generator>
		</id>
		<!-- property是除id以外的普通属性的映射 
			name:属性名 默认使用属性名
			cloumn(可选):填写列名
			type(可选):填写属性的类型,Java属性,hibernate属性,数据库属性
			not-null:默认false
			length(可选):配置数据库的列的长度,默认数据库类型最大长度	
		-->
		<property name="cust_name" column="cust_name"></property>
		<property name="cust_source" column="cust_source" ></property>
		<property name="cust_industry" column="cust_industry" ></property>
		<property name="cust_level" column="cust_level" ></property>
		<property name="cust_linkman" column="cust_linkman" ></property>
		<property name="cust_phone" column="cust_phone" ></property>
		<property name="cust_mobile" column="cust_mobile" ></property>
		<!-- 集合一对多 -->
		<!--name:集合的属性名,class:与外键关联的完整的类名 ,column:是哪个列为外键-->
		<!--级联操作:cascade=""  save-update:级联保存更新,delete:级联删除,
            all:级联删除和保存操作性质:是数据的操作的简化 -->
		<!-- inverse属性:配置关系是否维护 ,true:是让对方维护这个关系
			false:是双方都会维护的
			如果不配置是双方都会维护的
			原则:总有一方要维护关系
			只能是一的一方放弃维护关系,多的一方必须维护
		-->
		<!-- 
			fetch 决定加载的sql语句
				select: 使用单表查询
				join : 多表查询
				subselect:使用子查询
			lazy  决定加载时机
				false: 立即加载
				true:延迟jiazai
				extra:及其懒惰
		-->
		<set name="linkMens" inverse="true" lazy="true" fetch="select">
			<key column="lkm_cust_id"/>
			<one-to-many class="LinkMan"/>
		</set>
	</class>
</hibernate-mapping>
lazy="true" fetch="select":配置的配合:
//fetch:select 单表查询//lazy:true 使用时才加载集合数据.默认值
//fetch:select 单表查询//lazy:false 立即记载集合数据
//fetch:select 单表查询//lazy:extra 极其懒惰.与懒加载效果基本一致. 如果只获得集合的size.只查询集合的size(count语句)
//fetch:join	多表查询//lazy:true|false|extra 失效.立即加载.
            
查询:在service中可以先获得参数:
//service层:
String name=request.getprameter(name);
DetachedCriteria dc=DetachedCriteria.forClass(Customer.class);
dc.add(Restrictions.like("id",%+name+%));//拼装条件
需要同时传入对象的属性和值

遇到的坑:

​ 在使用配置文件时应注意:.hbm.xml映射文件和.cfg.xml配置文件必须在src和所建的包同级不然会报错:Could not locate cfg.xml resource [hibernate.cfg.xml]

​ 如果不在同一个包中则编译器不能找到这个文件,

package com.leo.api;

import java.util.List;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.query.Query;
import org.junit.Test;

import com.leo.domain.Customer;
import com.leo.domain.LinkMan;

/**
 * 懒加载策略
 * @author leoi555
 *
 */
public class Demo_get_load {
	/**
	 * get获得对象:
	 * 立即查询
	 */
	public void test(){
		//1 获得session
		Session session = HibernateUtil.openSession();
		//2 开启事务
		Transaction tx = session.beginTransaction();
		//-------------------------------------------------
		//3操作
		//1> 获得要操作的客户对象
		Customer c = session.get(Customer.class,5l);
		//2> 创建联系人
		
		//-------------------------------------------------
		//4提交事务
		tx.commit();
		//5关闭资源
		session.close();
	}
	/**
	 * load获得:延迟加载,语句在执行时不发送任何sql语句,会先返回一个代理对象,只有使用时才会执行查询
	 *是否延迟加载,可以配置class属性lazy:true;加载时不查询,使用的时候才查询。
	 *根据关联的session查询确保调用属性加载数据时sesion用保持打开
	 *默认是延迟加载
	 */
	
	
	public void test2(){
		//1 获得session
		Session session = HibernateUtil.openSession();
		//2 开启事务
		Transaction tx = session.beginTransaction();
		//-------------------------------------------------
		//3操作
		//1> 获得要操作的客户对象
		Customer c = session.load(Customer.class,5l);
		//2> 创建联系人
		
		//-------------------------------------------------
		//4提交事务
		tx.commit();
		//5关闭资源
		session.close();
	}
	/**
	 * 集合级别的关联
	 */
	public void test3(){
		//1 获得session
		Session session = HibernateUtil.openSession();
		//2 开启事务
		Transaction tx = session.beginTransaction();
		//-------------------------------------------------
		//3操作
		//1> 获得要操作的客户对象
		Customer c = session.load(Customer.class,5l);
		Set<LinkMan> linkMens= c.getLinkMens();//关联级别
		System.out.println(linkMens);
		//-------------------------------------------------
		//4提交事务
		tx.commit();
		//5关闭资源
		session.close();
	}
	//集合级别的关联
	//fetch:select 单表查询
	//lazy:true 使用时才加载集合数据.默认值
		@Test
		public void fun1(){
			Session session =  HibernateUtil.openSession();
			Transaction tx = session.beginTransaction();
			//----------------------------------------------------
			
			Customer c = session.get(Customer.class, 2l);
			
			Set<LinkMan> linkMens = c.getLinkMens();//关联级别
			
			System.out.println(linkMens);
			
			//----------------------------------------------------
			tx.commit();
			session.close();
			
		}
		
		//集合级别的关联
			//fetch:select 单表查询
			//lazy:false 立即记载集合数据
			@Test
			public void fun2(){
				Session session = HibernateUtil.openSession();
				Transaction tx = session.beginTransaction();
				//----------------------------------------------------
				
				Customer c = session.get(Customer.class, 2l);
				
				Set<LinkMan> linkMens = c.getLinkMens();//关联级别
				
				System.out.println(linkMens);
				
				//----------------------------------------------------
				tx.commit();
				session.close();
				
			}
			//集合级别的关联
			//fetch:select 单表查询
			//lazy:extra 极其懒惰.与懒加载效果基本一致. 如果只获得集合的size.只查询集合的size(count语句)
			@Test
			public void fun3(){
				Session session =  HibernateUtil.openSession();
				Transaction tx = session.beginTransaction();
				//----------------------------------------------------
				
				Customer c = session.get(Customer.class, 2l);
				
				Set<LinkMan> linkMens = c.getLinkMens();//关联级别
				
				System.out.println(linkMens.size());
				
				System.out.println(linkMens);
				
				//----------------------------------------------------
				tx.commit();
				session.close();
				
			}
			//集合级别的关联
			//fetch:join	多表查询
			//lazy:true|false|extra 失效.立即加载.不会进行懒加载
			@Test
			public void fun4(){
				Session session =  HibernateUtil.openSession();
				Transaction tx = session.beginTransaction();
				//----------------------------------------------------
				
				Customer c = session.get(Customer.class, 2l);
				
				Set<LinkMan> linkMens = c.getLinkMens();//关联级别
				
				System.out.println(linkMens.size());
				
				System.out.println(linkMens);
				
				//----------------------------------------------------
				tx.commit();
				session.close();
				
			}
			
			@Test
			//fetch: subselect 子查询
			//lazy: true 懒加载
			public void fun5(){
				Session session =  HibernateUtil.openSession();
				Transaction tx = session.beginTransaction();
				//----------------------------------------------------
					
				String  hql = "from Customer";
				
				Query query = session.createQuery(hql);
				
				List<Customer> list = query.list();
				
				for(Customer c:list){
					System.out.println(c);
					System.out.println(c.getLinkMens().size());
					System.out.println(c.getLinkMens());
				}
				
				//----------------------------------------------------
				tx.commit();
				session.close();
				
			}
			@Test
			//fetch: subselect 子查询
			//lazy: false 立即加载
			public void fun6(){
				Session session =  HibernateUtil.openSession();
				Transaction tx = session.beginTransaction();
				//----------------------------------------------------
					
				String  hql = "from Customer";
				
				Query query = session.createQuery(hql);
				
				List<Customer> list = query.list();
				
				for(Customer c:list){
					System.out.println(c);
					System.out.println(c.getLinkMens().size());
					System.out.println(c.getLinkMens());
				}
				
				//----------------------------------------------------
				tx.commit();
				session.close();
				
			}
			@Test
			//fetch: subselect 子查询
			//lazy: extra 极其懒惰
			public void fun7(){
				Session session = HibernateUtil.openSession();
				Transaction tx = session.beginTransaction();
				//----------------------------------------------------
					
				String  hql = "from Customer";
				
				Query query = session.createQuery(hql);
				
				List<Customer> list = query.list();
				
				for(Customer c:list){
					System.out.println(c);
					System.out.println(c.getLinkMens().size());
					System.out.println(c.getLinkMens());
				}
				
				//----------------------------------------------------
				tx.commit();
				session.close();
				
			}
		
			/**
			 * 反加载:
			 * 通过属性获取对象级别的加载
			 */
			@Test
			public void testOver(){
				Session session = HibernateUtil.openSession();
				Transaction tx = session.beginTransaction();
				//----------------------------------------------------
					
				LinkMan linkMan=session.get(LinkMan.class, 1l);
				Customer customer=linkMan.getCustomer();
					System.out.println(customer);
				//----------------------------------------------------
				tx.commit();
				session.close();
				
			}
}
package com.leo.api;

import javax.management.Query;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.leo.domain.Customer;
import com.leo.domain.LinkMan;

/**
 * 级联操作
 * @author leoi555
 *
 */
public class DemoToCascadeOntoMany {
	@Test
	//保存客户 以及客户 下的联系人
	//一个customer下有多个联系人对象
	public void fun1(){
		//1 获得session
		Session session = HibernateUtil.openSession();
		//2 开启事务
		Transaction tx = session.beginTransaction();
		//-------------------------------------------------
		//3操作
		Customer c = new Customer();
		c.setCust_name("传智播客");
		
		LinkMan lm1 = new LinkMan();
		lm1.setLkm_name("黎活明");
		
		LinkMan lm2 = new LinkMan();
		lm2.setLkm_name("刘悦东");
		
		//表达一对多,客户下有多个联系人
		//如果客户放弃维护联系人,维护的代码可以省略
		c.getLinkMens().add(lm1);
		c.getLinkMens().add(lm2);
		
		//表达对对对,联系人属于哪个客户
		lm1.setCustomer(c);
		lm2.setCustomer(c);
		
		
		session.save(c);
		session.save(lm1);
		session.save(lm2);
		//这就对应了在customer的一个实体对象中对应了两个外部的联系人对象
		//-------------------------------------------------
		//4提交事务
		tx.commit();
		//5关闭资源
		session.close();
	}

	//为客户增加联系人
	public void fun2(){
		//1 获得session
		Session session = HibernateUtil.openSession();
		//2 开启事务
		Transaction tx = session.beginTransaction();
		//-------------------------------------------------
		//3操作
		//1> 获得要操作的客户对象
		Customer c = session.get(Customer.class,5l);
		//2> 创建联系人
		LinkMan lm1 = new LinkMan();
		lm1.setLkm_name("郝强勇");
		//3> 将联系人添加到客户,将客户设置到联系人中
		c.getLinkMens().add(lm1);
		lm1.setCustomer(c);
		//4> 执行保存
		session.save(lm1);
		//-------------------------------------------------
		//4提交事务
		tx.commit();
		//5关闭资源
		session.close();
	}
	
	//为客户删除联系人只是把外键得映射给删除了但是还是不可以删除这个表中的数据
	//同样也可可以直接把表中的信息给删除去,直接用session.delete(object);删除你所查询到的对象即可
	public void fun3(){
		//1 获得session
		Session session = HibernateUtil.openSession();
		//2 开启事务
		Transaction tx = session.beginTransaction();
		//-------------------------------------------------
		//在数据库中如果有对象引用这个属性时,删除其中一个是不可以删除的
		//删除的时候需要用级联删除,如果要删除可以用:inverse="false";这是维护外键,可以直接删并设置外键为空
		//或者用 不维护外键:inverse="true",casecade="delete";级联删除;
		//3操作
		//1> 获得要操作的客户对象
		Customer c = session.get(Customer.class,5l);
		//2> 获得要移除的联系人
		LinkMan lm = session.get(LinkMan.class, 3l);
		//3> 将联系人从客户集合中移除
		c.getLinkMens().remove(lm);
		lm.setCustomer(null);
		//删除这个对应的数据并且把数据给删除掉
		session.delete(lm);
		//-------------------------------------------------
		//4提交事务
		tx.commit();
		//5关闭资源
		session.close();
	}
}

linkman.hbm.xml配置:
以及customer.hbm.xml配置

<?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 package="com.leo.domain">
	<class name="LinkMan" table="cust_linkman">
	<!-- id映射主键属性name:填对应的属性名,column列名 -->
		<id name="lkm_id"  >
			<generator class="native"></generator>
		</id>
		<property name="lkm_gender"  ></property>
		<property name="lkm_name"  ></property>
		<property name="lkm_phone"  ></property>
		<property name="lkm_email"  ></property>
		<property name="lkm_qq"  ></property>
		<property name="lkm_mobile"  ></property>
		<property name="lkm_memo"  ></property>
		<property name="lkm_position"  ></property>
		<!-- 
		fetch 决定加载的sql语句
			select: 使用单表查询
			join : 多表查询
		lazy  决定加载时机
			false: 立即加载
			proxy: 由customer的类级别加载策略决定.
			为了提高效率应选择select,lazy为true,使用默认值
		 -->
		 <!--级联操作:cascade=""  save-update:级联保存更新,delete:级联删除,all:级联删除和保存
			操作性质:是数据的操作的简化
			多对一的单向的操作,需要在持久化得类的外键中引入另一个表中的主键,
			这是使用的是双向关联
		  -->
		  <!-- 在多的一方是不能够放弃维护关系的,外键字段是多的一方的列 -->	 
		<many-to-one name="customer" column="lkm_cust_id" class="Customer" fetch="join" lazy="proxy"  >
		</many-to-one>
	</class>
</hibernate-mapping>
<?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 package="com.leo.domain">
	<class name="Customer" table="cust_customer">
	<!-- id映射主键属性name:填对应的属性名,column列名 -->
		<id name="cust_id" column="cust_id">
			<!-- 生成主键策略
				主键的生成规则:
				identity :主键自增,录入是不需要指定id的
				increate:主键自增,由hinbernate维护,每次会查询id最大值,然后另其+1(勿用线程安全问题)
				sequence:oracle主键生成策略
				hilo:一种主键自增的策略;高低算法,由hinbernate维护 (不需要用)
				native:hilo+sequence+identity自动三选一,有配置文件筛选出来;
				uuid:string类型的主键,产生随机数id
				assigned:自然生成,有开发人员维护主键
			 -->
			<generator class="identity"></generator>
		</id>
		<!-- property是除id以外的普通属性的映射 
			name:属性名 默认使用属性名
			cloumn(可选):填写列名
			type(可选):填写属性的类型,Java属性,hibernate属性,数据库属性
			not-null:默认false
			length(可选):配置数据库的列的长度,默认数据库类型最大长度	
		-->
		<property name="cust_name" column="cust_name"></property>
		<property name="cust_source" column="cust_source" ></property>
		<property name="cust_industry" column="cust_industry" ></property>
		<property name="cust_level" column="cust_level" ></property>
		<property name="cust_linkman" column="cust_linkman" ></property>
		<property name="cust_phone" column="cust_phone" ></property>
		<property name="cust_mobile" column="cust_mobile" ></property>
		<!-- 集合一对多 -->
		<!--name:集合的属性名,class:与外键关联的完整的类名 ,column:是哪个列为外键  -->
		<!--级联操作:cascade=""  save-update:级联保存更新,delete:级联删除,all:级联删除和保存
			操作性质:是数据的操作的简化
		  -->
		  <!-- inverse属性:配置关系是否维护 ,true:是让对方维护这个关系
		  	false:是双方都会维护的
		  	如果不配置是双方都会维护的
		  	原则:总有一方要维护关系
		  	只能是一的一方放弃维护关系,多的一方必须维护
		  	-->
<!-- 
		集合的关联
		fetch 决定加载的sql语句
			select: 使用单表查询
			join : 多表查询
			subselect:使用子查询
		lazy  决定加载时机
			false: 立即加载
			true:延迟jiazai
			extra:及其懒惰
		 -->
		<set name="linkMens" inverse="true" lazy="true" fetch="select">
			<key column="lkm_cust_id"/>
			<one-to-many class="LinkMan"/>
		</set>
	</class>
</hibernate-mapping>

用到的获取session对象的util类:

package com.leo.api;
/**
 * 工具类
 * @author leoi555
 *
 */
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
/**
 * HibernateUtil使用
 * @author leoi555
 *
 */
public class HibernateUtil {
	private static SessionFactory sessionFactory;
	static{
		Configuration cfg=new Configuration().configure();//加载hibernate配置文件
		sessionFactory=cfg.buildSessionFactory();//创建session
	}
	//获得的openSessioin
		public static Session openSession() {
			Session session=sessionFactory.openSession();
			if (session!=null){
				return session;
			}
			return session;
		}
	//获得currentSession
		public static Session getCurrentsesion() {
			Session session=sessionFactory.getCurrentSession();
			if (session==null){
					System.out.println("获得session失败");
			}
			return session;	
		}
		public static void main(String[] args) {
			System.out.println(HibernateUtil.openSession());
		}
		
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay三石 [Alay Kay]

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值