hibernate小结(3)

1、表与表之间关系

1、 一对多

(1)分类和商品关系,一个分类里面有多个商品,一个商品只能属于一个分类 

(2)客户和联系人是一对多关系

    - 客户:与公司有业务往来,百度、新浪、360

    - 联系人:公司里面的员工,百度里面有很多员工,联系员工

    ** 公司和公司员工的关系

    -   客户是一,联系人是多

    - 一个客户里面有多个联系人,一个联系人只能属于一个客户

(3)一对多建表:通过外键建立关系


2 、多对多

(1)订单和商品关系,一个订单里面有多个商品,一个商品属于多个订单

(2)用户和角色多对多关系

    - 用户:小王、小马、小宋

    - 角色:总经理、秘书、司机、保安

    ** 比如小王可以 是总经理,可以是司机

    ** 比如小宋可以是司机,可以是秘书,可以保安

    ** 比如小马可以是 秘书,可以是总经理

    -  一个用户里面可以有多个角色,一个角色里面可以有多个用户

(3)多对多建表:创建第三张表维护关系

3、 一对一

(1)在中国,一个男人只能有一个妻子,一个女人只能有一个丈夫


2、Hibernate的一对多操作(重点

1、一对多映射配置

以客户和联系人为例:客户是一,联系人是多

    第一步 创建两个实体类,客户和联系人

    第二步 让两个实体类之间互相表示

(1)在客户实体类里面表示多个联系人

    - 一个客户里面有多个联系人,在客户实体类中表示多个联系人,一个客户有多个联系人
       hibernate中要求使用    集合表示多的数据,要求使用set集合,set是无序的且不能有重复元素

package cn.itcast.entity;


import java.util.HashSet;


public class Customer {
	//客户id
	private Integer cid;
	//客户名称
	private String custName;
	//客户级别
	private String custLevel;
	//客户来源
	private String custSource;
	//联系电话
	private String custPhone;
	//手机
	private String custMobile;
	
	// 在客户实体类中表示多个联系人,一个客户有多个联系人
	// hibernate中要求使用集合表示多的数据,要求使用set集合,set是无序的且不能有重复元素
	private HashSet<LinkMan> setLinkMan = new HashSet<LinkMan>();


	// 生成setlinkMan的get与set
	public HashSet<LinkMan> getSetLinkMan() {
		return setLinkMan;
	}


	public void setSetLinkMan(HashSet<LinkMan> setLinkMan) {
		this.setLinkMan = setLinkMan;
	}


	public Integer getCid() {
		return cid;
	}
	public void setCid(Integer cid) {
		this.cid = cid;
	}
	public String getCustName() {
		return custName;
	}
	public void setCustName(String custName) {
		this.custName = custName;
	}
	public String getCustLevel() {
		return custLevel;
	}
	public void setCustLevel(String custLevel) {
		this.custLevel = custLevel;
	}
	public String getCustSource() {
		return custSource;
	}
	public void setCustSource(String custSource) {
		this.custSource = custSource;
	}
	public String getCustPhone() {
		return custPhone;
	}
	public void setCustPhone(String custPhone) {
		this.custPhone = custPhone;
	}
	public String getCustMobile() {
		return custMobile;
	}
	public void setCustMobile(String custMobile) {
		this.custMobile = custMobile;
	}
}

(2)在联系人实体类里面表示所属客户

        - 一个联系人只能属于一个客户,在联系人的实体类中创建客户对象


package cn.itcast.entity;

public class LinkMan {
	private Integer lkm_id; // 联系人编号(主键)
	private String lkm_name;// 联系人姓名
	private String lkm_gender;// 联系人性别
	private String lkm_phone;// 联系人办公电话
	
	//在联系人人实体类里面表示所属客户,一个联系人只能属于一个客户
	private Customer customer;
	
	public Customer getCustomer() {
		return customer;
	}
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
	public Integer getLkm_id() {
		return lkm_id;
	}
	public void setLkm_id(Integer lkm_id) {
		this.lkm_id = lkm_id;
	}
	public String getLkm_name() {
		return lkm_name;
	}
	public void setLkm_name(String lkm_name) {
		this.lkm_name = lkm_name;
	}
	public String getLkm_gender() {
		return lkm_gender;
	}
	public void setLkm_gender(String lkm_gender) {
		this.lkm_gender = lkm_gender;
	}
	public String getLkm_phone() {
		return lkm_phone;
	}
	public void setLkm_phone(String lkm_phone) {
		this.lkm_phone = lkm_phone;
	}
}

第三步 配置映射关系

(1)一般一个实体类对应一个映射文件

(2)把映射最基本配置完成

(3)在映射文件中,配置一对多关系

        - 在客户映射文件中,表示所有联系人


具体配置文件:

<?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>
	<!-- 1 配置类和表对应 class标签 name属性:实体类全路径 table属性:数据库表名称 -->
	<class name="cn.itcast.entity.Customer" table="t_customer">
		<id name="cid" column="cid">
			<generator class="native"></generator>
		</id>
		<property name="custName" column="custName"></property>
		<property name="custLevel" column="custLevel"></property>
		<property name="custSource" column="custSource"></property>
		<property name="custPhone" column="custPhone"></property>
		<property name="custMobile" column="custMobile"></property>

		<!-- 在客户映射文件中,表示所有联系人 使用set标签表示所有联系人 set标签里面有name属性: 属性值写在客户实体类里面表示联系人的set集合名称 
			inverse属性默认值:false不放弃关系维护 true表示放弃关系维护 -->
		<set name="setLinkMan" inverse="true">
			<!-- 一对多建表,有外键 hibernate机制:双向维护外键,在一和多那一方都配置外键 column属性值:外键名称 -->
			<key column="clid"></key>
			<!-- 客户所有的联系人,class里面写联系人实体类全路径 -->
			<one-to-many class="cn.itcast.entity.LinkMan" />
		</set>
	</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>
	<!-- 1 配置类和表对应 class标签 name属性:实体类全路径 table属性:数据库表名称 -->
	<class name="cn.itcast.entity.LinkMan" table="t_linkman">
		<id name="lkm_id" column="lkm_id">
			<generator class="native"></generator>
		</id>
		<property name="lkm_name" column="lkm_name"></property>
		<property name="lkm_gender" column="lkm_gender"></property>
		<property name="lkm_phone" column="lkm_phone"></property>

		<!-- 表示联系人所属客户 name属性:因为在联系人实体类使用customer对象表示,写customer名称 class属性:customer全路径 
			column属性:外键名称 -->
		<!-- 一对多实体类配置 -->
		<many-to-one name="customer" class="cn.itcast.entity.Customer"
			column="clid"></many-to-one>
	</class>
</hibernate-mapping>


第四步  创建核心配置文件,把映射文件引入到核心配置文件中


具体配置文件为:
<?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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql:///hibernate_day03_Customer</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">Huang123</property>

		<!-- 第二部分: 配置hibernate信息 可选的 -->
		<!-- 输出底层sql语句 -->
		<property name="hibernate.show_sql">true</property>
		<!-- 输出底层sql语句格式 -->
		<property name="hibernate.format_sql">true</property>
		<!-- hibernate帮创建表,需要配置之后 update: 如果已经有表,更新,如果没有,创建 -->
		<property name="hibernate.hbm2ddl.auto">update</property>
		<!-- 配置数据库方言 在mysql里面实现分页 关键字 limit,只能使用mysql里面 在oracle数据库,实现分页rownum 让hibernate框架识别不同数据库的自己特有的语句 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<!--配置本地线程绑定session -->
		<property name="hibernate.current_session_context_class">thread</property>
		<!-- 第三部分: 把映射文件放到核心配置文件中 必须的 -->
		<mapping resource="com/hibernate_stu/entity/Customer/User.hbm.xml" />
		<mapping resource="com/hibernate_stu/entity/Customer/User.hbm.xml" />
	</session-factory>
</hibernate-configuration>
运行HibernateUtils类进行测试:

HibernateUtils类为(直接JavaApplication执行):

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
	static Configuration cfg = null;
	static SessionFactory sessionFactory = null;
	//静态代码块实现
	static {
		//加载核心配置文件
		cfg = new Configuration();
		cfg.configure();
		sessionFactory = cfg.buildSessionFactory();
	}
	//提供返回与本地线程绑定的session
	public static Session getSessionObject(){
		return sessionFactory.getCurrentSession();
	}
	//提供方法返回sessionFactory
	public static SessionFactory getSessionFactory() {
		return sessionFactory;
	}	
	public static void main(String[] args) {
		
	}
}

测试结果:在数据库建立表


3、一对多级联操作(重点

级联操作

1、 级联保存

(1)添加一个客户,为这个客户添加多个联系人

2 、级联删除

(1)删除某一个客户,这个客户里面的所有的联系人也删除

1、一对多级联保存

(2)添加客户,为这个客户添加一个联系人

复杂写法:

// 演示Hibernate级联保存,麻烦方式
	@Test
	public void testAddDemo1() {
		Transaction tr = null;
		Session session = null;
		SessionFactory sessionFactory = null;
		try {
			sessionFactory = HibernateUtils.getSessionFactory();
			session = sessionFactory.openSession();
			tr = session.beginTransaction();
			// 添加一个客户,并对客户进行级联保存
			// 1.创建客户与联系人对象
			Customer customer = new Customer();
			customer.setCustName("百度");
			customer.setCustLevel("vip");
			customer.setCustSource("网络");
			customer.setCustPhone("110");
			customer.setCustMobile("119");
			LinkMan linkMan = new LinkMan();
			linkMan.setLkm_name("lucy");
			linkMan.setLkm_gender("gender");
			linkMan.setLkm_phone("911");
			// 2.在客户中表示联系人,在联系人中表示客户,建立客户对象与联系人对象的关系
			// 两个对象建立关系
			// 2.1在客户中表示所有联系人,将联系人对象放到客户实体类对象的Set集合中
			customer.getSetLinkMan().add(linkMan);
			// 2.2将客户对象放到联系人中
			linkMan.setCustomer(customer);
			// 保存到数据库
			session.save(customer);
			session.save(linkMan);
			tr.commit();
		} catch (Exception e) {
			tr.rollback();
			e.printStackTrace();
		} finally {
			// session.close();
			// sessionFactory.close();
		}
	}

添加到数据库:



(2)简化写法

    - 一般根据客户添加联系人

    第一步 在客户映射文件中进行配置

    - 在客户映射文件里面set标签进行配置


<set name="setLinkMan" cascade="save-update">
			<!-- 一对多建表,有外键 hibernate机制:双向维护外键,在一和多那一方都配置外键 column属性值:外键名称 -->
			<key column="clid"></key>
			<!-- 客户所有的联系人,class里面写联系人实体类全路径 -->
			<one-to-many class="cn.itcast.entity.LinkMan" />
		</set>

    - 创建客户和联系人对象,只需要把联系人放到客户里面就可以了,最终只需要保存客户就可以了

//演示一对多级联保存

    @Test

    public void testAddDemo2() {

       SessionFactory sessionFactory = null;

       Sessionsession = null;

       Transactiontx = null;

       try{

           //得到sessionFactory

           sessionFactory =HibernateUtils.getSessionFactory();

           //得到session

           session= sessionFactory.openSession();

           //开启事务

           tx= session.beginTransaction();

           //添加一个客户,为这个客户添加一个联系人

           //1创建客户和联系人对象

           Customercustomer = new Customer();

           customer.setCustName("百度");

           customer.setCustLevel("普通客户");

           customer.setCustSource("网络");

           customer.setCustPhone("110");

           customer.setCustMobile("999");
      
           LinkManlinkman = new LinkMan();

           linkman.setLkm_name("小宏");

           linkman.setLkm_gender("男");

           linkman.setLkm_phone("911");

           //2把联系人放到客户里面

           customer.getSetLinkMan().add(linkman);

           //3保存客户

           session.save(customer);
     
           //提交事务

           tx.commit();

       }catch(Exceptione) {

           tx.rollback();

       }finally{

           session.close();

           //sessionFactory不需要关闭

           sessionFactory.close();
       }

    }

4、一对多级联删除

1 、删除某个客户,把客户里面所有的联系人删除

2、 具体实现

第一步 在客户映射文件set标签,进行配置

(1)使用属性cascade属性值 delete


<set name="setLinkMan" cascade="save-update,delete">
			<!-- 一对多建表,有外键 hibernate机制:双向维护外键,在一和多那一方都配置外键 column属性值:外键名称 -->
			<key column="clid"></key>
			<!-- 客户所有的联系人,class里面写联系人实体类全路径 -->
			<one-to-many class="cn.itcast.entity.LinkMan" />
		</set>

第二步 在代码中直接删除客户

(1)根据id查询对象,调用session里面delete方法删除


3 、执行过程:

(1)根据id查询客户


(2)根据外键id值查询联系人

  

(3)把联系人外键设置为null


(4)删除联系人和客户

5、一对多修改操作(inverse属性)

1 、让lucy联系人所属客户不是传智播客,而是百度

2 、inverse属性

(1)因为hibernate的机制是双向维护外键,在客户和联系人里面都需要维护外键,修改客户时候修改一次外键,修改联系人时候也修改一次外键,造成效率问题


(2)解决方式:让其中的一方不维护外键

- 一对多里面,让其中一方放弃外键维护(一的一方放弃维护外键)

-举例: 一个国家有总统,国家有很多人,总统不能认识国家所有人,国家所有人可以认识总统

(3)具体实现:

在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性

<!-- 在客户映射文件中,表示所有联系人 使用set标签表示所有联系人 set标签里面有name属性: 属性值写在客户实体类里面表示联系人的set集合名称 
			inverse属性默认值:false不放弃关系维护 true表示放弃关系维护 -->
		<set name="setLinkMan" inverse="true">
			<!-- 一对多建表,有外键 hibernate机制:双向维护外键,在一和多那一方都配置外键 column属性值:外键名称 -->
			<key column="clid"></key>
			<!-- 客户所有的联系人,class里面写联系人实体类全路径 -->
			<one-to-many class="cn.itcast.entity.LinkMan" />
		</set>

6、Hibernate多对多操作

1、多对多映射配置

以用户和角色为例演示

第一步 创建实体类,用户和角色

第二步 让两个实体类之间互相表示

(1)一个用户里面表示所有角色,使用set集合

(2)一个角色有多个用户,使用set集合


第三步 配置映射关系

(1)基本配置

(2)配置多对多关系

        - 在用户里面表示所有角色,使用set标签


<?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="com_hibernatestu.entity.User" table="t_user">
		<id name="user_id" column="user_id">
			<generator class="native"></generator>
		</id>
		<property name="user_name" column="user_name"></property>
		<property name="user_password" column="user_password"></property>

		<!-- 在用户中表示有多个角色,使用set标签 name属性:角色set集合名称 table属性:第三张表名称 -->
		<!--级联保存操作 cascade="save-update" -->
		<set name="roleSet" table="user_role" cascade="save-update,delete">

			<!-- key里的column配置:当前的映射文件在第三张表的外键的名称 -->
			<key column="userid"></key>
			<!-- class是角色全路径,column是角色在第三张表的外键名称 -->
			<many-to-many class="com_hibernatestu.entity.Role"
				column="roleid"></many-to-many>
		</set>
	</class>
</hibernate-mapping>

- 在角色里面表示所有用户,使用set标签


<?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="com_hibernatestu.entity.Role" table="t_role">
		<id name="role_id" column="role_id">
			<generator class="native"></generator>
		</id>
		<property name="role_name" column="role_name"></property>
		<property name="role_memo" column="role_memo"></property>
		<!-- 在角色中表示所有的用户也是使用set -->
		<set name="userSet" table="user_role">
			<key column="roleid"></key>
			<many-to-many class="com_hibernatestu.entity.Role"
				column="userid"></many-to-many>

		</set>
	</class>

</hibernate-mapping>
注意:在用户里面表示所有角色,在角色里面表示所有用户,容易弄混,下面是配置的对应关系

第四步 在核心配置文件中引入映射文件,实体类的全路径


测试:



7、多对多级联保存

根据用户保存角色

第一步 在用户配置文件中set标签进行配置,cascade值save-update


第二步 写代码实现

(1)创建用户和角色对象,把角色放到用户里面,最终保存用户就可以了

//演示多对多修级联保存

    @Test

    publicvoid testSave(){

       SessionFactorysessionFactory = null;

       Sessionsession = null;

       Transactiontx = null;

        try {

           //得到sessionFactory

           sessionFactory= HibernateUtils.getSessionFactory();

           //得到session

           session= sessionFactory.openSession();

           //开启事务

           tx= session.beginTransaction();   

           //添加两个用户,为每个用户添加两个角色

           //1创建对象

           Useruser1 = new User();

           user1.setUser_name("lucy");

           user1.setUser_password("123");          

           Useruser2 = new User();

           user2.setUser_name("mary");

           user2.setUser_password("456");
        

           Role r1 = new Role();

           r1.setRole_name("总经理");

           r1.setRole_memo("总经理");         

           Role r2 = new Role();

           r2.setRole_name("秘书");

           r2.setRole_memo("秘书");         

           Role r3 = new Role();

           r3.setRole_name("保安");

           r3.setRole_memo("保安");
        

           //2 建立关系,把角色放到用户里面

           // user1 -- r1/r2

           user1.getSetRole().add(r1);

           user1.getSetRole().add(r2);
         

           // user2 -- r2/r3

           user2.getSetRole().add(r2);

           user2.getSetRole().add(r3);
         

           //3 保存用户
           session.save(user1);

           session.save(user2);          

           //提交事务

           tx.commit(); 

       }catch(Exception e) {

           tx.rollback();
       }finally{

           session.close();

           //sessionFactory不需要关闭

           sessionFactory.close();

       }
    }


8、多对多级联删除

第二步 写代码实现

(1)创建用户和角色对象,把角色放到用户里面,最终保存用户就可以了

第一步 在set标签进行配置,cascade值delete


第二步 删除用户

9、维护第三张表关系

多对对的表关系中,一般是通过维护第三张表来维护表之间的关系

(1)创建用户和角色对象,把角色放到用户里面,最终保存用户就可以了

1 、用户和角色多对多关系,维护关系通过第三张表维护

2 、让某个用户有某个角色

        第一步 根据id查询用户和角色

        第二步 把角色放到用户里面

                (1)把角色对象放到用户set集合 


3 、让某个用户没有某个角色

        第一步 根据id查询用户和角色

        第二步 从用户里面把角色去掉

                 (1)从set集合里面把角色移除


第二步 写代码实现

(1)创建用户和角色对象,把角色放到用户里面,最终保存用户就可以了

public class TestAdd {
	@Test
	//多对多级联添加
	//1.在用户配置文件中set标签进行配置,cascade=“save-update”
	//2.创建用户和角色对象,将角色放到用户中
	//3.保存用户
	public void testAddDemo1() {
		Transaction tr = null;
		Session session = null;
		SessionFactory sessionFactory = null;
		try {
			sessionFactory=HibernateUtils.getSessionFactory();
			session = sessionFactory.openSession();
			tr = session.beginTransaction();

			//添加两个用户,为,每个用户添加两个角色
			User user1= new User();
			user1.setUser_name("小陈");
			user1.setUser_password("123");
			
			User user2 = new User();
			user2.setUser_name("小董");
			user2.setUser_password("465");
			
			Role role1=new Role();
			role1.setRole_memo("保洁");
			role1.setRole_name("保洁");
			
			Role role2=new Role();
			role2.setRole_memo("技术员");
			role2.setRole_name("技术员");
			
			Role role3=new Role();
			role3.setRole_memo("管理");
			role3.setRole_name("管理");
			
			//建立角色与用户的关系,将角色放到用户中
			//user1---role1 and role2
			user1.getRoleSet().add(role1);
			user1.getRoleSet().add(role2);		
			//User2---role2 and role3
			user2.getRoleSet().add(role2);
			user2.getRoleSet().add(role3);
			//保存用户
			session.save(user1);
			session.save(user2);
			
			tr.commit();
		} catch (Exception e) {
			tr.rollback();
			e.printStackTrace();
		} finally {
			session.close();
			sessionFactory.close();
		}
	}
}

本章小结:

1、 列表功能实现

2、 表与表之间关系回顾

(1)一对多(客户和联系人)

(2)多对多(用户和角色) 

2 、hibernate一对多操作

(1)一对多映射配置

(2)一对多级联保存

(3)一对多级联删除

(4)inverse属性

3、 hibernate多对多操作

(1)多对多映射配置

(2)多对多级联保存(重点)

(3)多对多级联删除

(4)维护第三张表
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值