这是黑马视频的学习笔记
表与表的关系的复习
一对多
1. 分类和商品,一类有多个商品,一个商品只属于一类
2.客户公司和联系人员工,一个客户公司有多个联系人员工,但一个联系人只属于一个客户公司
3.一对多关系的建表:通过外键建立两张表之间的关系
多对多
1. 订单和商品,一个订单含有多个商品,一个商品也会属于多个订单
2.用户和角色(职位)的关系
- 用户:小王,小马,小宋
- 角色:总经理,秘书,司机,保安
- 比如小王 可以 是总经理,可以是司机
- 比如小宋 可以 是司机,可以是秘书,可以是保安
- 比如小马 可以 是秘书,可以是总经理
- 一个用户里面可以由多个角色,一个角色里面可以有多个用户
一对一(很少用)
。。。。。
使用hibernate完成一对多的操作
映射配置
1.以客户和联系人威力,先创建两个实体类。并且让两个实体类互相表示对方
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;
}
}
package cn.itcast.entity;
import java.util.HashSet;
import java.util.Set;
public class Customer {
private Integer cid;
private String custName;
private String custLevel;
private String custSource;
private String custPhone;
private String custMobil;
private Set<LinkMan> setLinkMan=new HashSet<LinkMan>();
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public Set<LinkMan> getSetLinkMan() {
return setLinkMan;
}
public void setSetLinkMan(Set<LinkMan> setLinkMan) {
this.setLinkMan = setLinkMan;
}
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 getCustMobil() {
return custMobil;
}
public void setCustMobil(String custMobil) {
this.custMobil = custMobil;
}
}
2. 配置每个类到表的映射文件,并且配置两个类之间的映射
联系人实体类的映射文件
<?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="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属性,因为联系人实体类使用custome对象表示,写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-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<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="custPhone" column="custPhone"></property>
<property name="custMobil" column="custMobil"></property>
<set name="setLinkMan">
<!--双向维护外键-->
<key column="clid"></key>
<one-to-many class="cn.itcast.entity.LinkMan"/>
</set>
</class></hibernate-mapping>
3.创建核心配置文件,在核心配置文件中引入实体类到表的映射文件
<!--把映射文件放到核心配置文件中,必须的 -->
<mapping resource="cn/itcast/entity/Customer.hbm.xml"/>
<mapping resource="cn/itcast/entity/LinkMan.hbm.xml"/>
级联保存
添加一个客户,并且为这个客户添加多个联系人
复杂写法
package cn.itcast.hibernatetest;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.entity.Customer;
import cn.itcast.entity.LinkMan;
import cn.itcast.utils.HibernateUtils;
public class HibernateOneToMany {
//演示一对多级联保存
@Test
public void testAddDemo1(){
SessionFactory sessionFactory=null;
Session session=null;
Transaction tx=null;
try {
sessionFactory=HibernateUtils.getSessionFactory();
session=sessionFactory.openSession();
tx=session.beginTransaction();
//添加一个客户,为这个客户添加一个联系人
//1.创建客户和联系人对象
Customer customer=new Customer();
customer.setCustName("传智播客");
customer.setCustLevel("vip");
customer.setCustSource("网络");
customer.setCustPhone("110");
customer.setCustMobil("999");
LinkMan linkMan=new LinkMan();
linkMan.setLkm_name("lucy");
linkMan.setLkm_gender("男");
linkMan.setLkm_phone("911");
//2.在客户里面表示联系人,在联系人里面表示客户
//建立客户对象和联系人对象之间的关系
//2.1 把联系人对象放到客户对象的set集合里面
customer.getSetLinkMan().add(linkMan);
//2.2 把客户对象放到联系人对象里面
linkMan.setCustomer(customer);
//3.保存到数据库
session.save(customer);
session.save(linkMan);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
sessionFactory.close();//web项目不需要关闭
}
}
}
简化写法
一般根据客户添加联系人,所以要先在客户映射文件中进行配置
<?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="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="custPhone" column="custPhone"></property>
<property name="custMobil" column="custMobil"></property>
<set name="setLinkMan" cascade="save-update">
<!-- 一对多建表,有外键
hibernate机制:双向维护外键,一和多的那一方都配置外键
column属性:外键名称 -->
<key column="clid"></key>
<one-to-many class="cn.itcast.entity.LinkMan"/>
</set>
</class>
</hibernate-mapping>
在代码的改变,只需要把联系人放到客户里面即可
package cn.itcast.hibernatetest;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.entity.Customer;
import cn.itcast.entity.LinkMan;
import cn.itcast.utils.HibernateUtils;
public class HibernateOneToMany {
//演示一对多级联保存
@Test
public void testAddDemo1(){
SessionFactory sessionFactory=null;
Session session=null;
Transaction tx=null;
try {
sessionFactory=HibernateUtils.getSessionFactory();
session=sessionFactory.openSession();
tx=session.beginTransaction();
//添加一个客户,为这个客户添加一个联系人
//1.创建客户和联系人对象
Customer customer=new Customer();
customer.setCustName("传智播客");
customer.setCustLevel("vip");
customer.setCustSource("网络");
customer.setCustPhone("110");
customer.setCustMobil("999");
LinkMan linkMan=new LinkMan();
linkMan.setLkm_name("lucy");
linkMan.setLkm_gender("男");
linkMan.setLkm_phone("911");
//2 把联系人对象放到客户对象的set集合里面
customer.getSetLinkMan().add(linkMan);
//3.保存到数据库
session.save(customer);
session.save(linkMan);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
sessionFactory.close();//web项目不需要关闭
}
}
}
级联删除
删除一个客户,这个客户里面所有的联系人也要删除
1.配置客户映射文件的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="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="custPhone" column="custPhone"></property>
<property name="custMobil" column="custMobil"></property>
<set name="setLinkMan" cascade="save-update,delete">
<!-- 一对多建表,有外键
hibernate机制:双向维护外键,一和多的那一方都配置外键
column属性:外键名称 -->
<key column="clid"></key>
<one-to-many class="cn.itcast.entity.LinkMan"/>
</set>
</class>
</hibernate-mapping>
删除代码实现:
package cn.itcast.hibernatetest;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import cn.itcast.entity.Customer;
import cn.itcast.entity.LinkMan;
import cn.itcast.utils.HibernateUtils;
public class HibernateOneToMany {
//演示一对多级联删除
@Test
public void testDelete(){
SessionFactory sessionFactory=null;
Session session=null;
Transaction tx=null;
try {
sessionFactory=HibernateUtils.getSessionFactory();
session=sessionFactory.openSession();
tx=session.beginTransaction();
//1.根据id查询客户对象
Customer customer=session.get(Customer.class, 3);
//2 调用方法删除
session.delete(customer);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
sessionFactory.close();//web项目不需要关闭
}
}
}
执行过程:根据id查询客户=====》根据外键值查询联系人=====》把联系人的外键设置成null====》删除联系人和客户
一对多修改操作
让一个联系人所属的客户改变成另一客户
//演示一对多级联修改
@Test
public void testUpdate(){
SessionFactory sessionFactory=null;
Session session=null;
Transaction tx=null;
try {
sessionFactory=HibernateUtils.getSessionFactory();
session=sessionFactory.openSession();
tx=session.beginTransaction();
//1.根据id查询联系人,再根据另一个id客户对象
Customer baidu=session.get(Customer.class, 1);
LinkMan linkMan=session.get(LinkMan.class, 2);
//2 设置持久态对象的值
//把联系人放到客户里面
baidu.getSetLinkMan().add(linkMan);
// 把客户放到联系人里面
linkMan.setCustomer(baidu);
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
session.close();
sessionFactory.close();//web项目不需要关闭
}
}
inverse属性
因为hibernate双向维护外键机制,在客户和联系人里面都要维护外键,修改客户和修改联系人共产生两次外键修改。造成性能问题
解决方法:让其中一方放弃维护外键,一的那一方放弃维护
具体实现:
<!--inverse属性的默认值是false,表示不放弃维护。改成true就表示放弃 -->
<set name="setLinkMan" inverse="true" cascade="save-update,delete">
<!-- 一对多建表,有外键
hibernate机制:双向维护外键,一和多的那一方都配置外键
column属性:外键名称 -->
<key column="clid"></key>
<one-to-many class="cn.itcast.entity.LinkMan"/>
</set>
使用hibernate完成多对多的操作
多对多映射配置
以用户和角色为例
1. 创建两个实体类对象,并且让两个实体类互相表示
用户实体类
package cn.itcast.manytomany;
import java.util.HashSet;
import java.util.Set;
public class User {
private Integer user_id;
private String user_name;
private String user_password;
private Set<Role> setRole=new HashSet<Role>();
public Set<Role> getSetRole() {
return setRole;
}
public void setSetRole(Set<Role> setRole) {
this.setRole = setRole;
}
public Integer getUser_id() {
return user_id;
}
public void setUser_id(Integer user_id) {
this.user_id = user_id;
}
public String getUser_name() {
return user_name;
}
public void setUser_name(String user_name) {
this.user_name = user_name;
}
public String getUser_password() {
return user_password;
}
public void setUser_password(String user_password) {
this.user_password = user_password;
}
}
角色实体类
package cn.itcast.manytomany;
import java.util.HashSet;
import java.util.Set;
public class Role {
private Integer role_id;
private String role_name;
private String role_memo;
private Set<User> setUser=new HashSet<User>();
public Set<User> getSetUser() {
return setUser;
}
public void setSetUser(Set<User> setUser) {
this.setUser = setUser;
}
public Integer getRole_id() {
return role_id;
}
public void setRole_id(Integer role_id) {
this.role_id = role_id;
}
public String getRole_name() {
return role_name;
}
public void setRole_name(String role_name) {
this.role_name = role_name;
}
public String getRole_memo() {
return role_memo;
}
public void setRole_memo(String role_memo) {
this.role_memo = role_memo;
}
}
2. 配置映射文件
用户映射文件
<?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="cn.itcast.manytomany.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:实体类中的角色集合变量
table属性:第三张表的名称 -->
<set name="setRole" table="user_role" cascade="save-update,delete">
<!-- key标签里配置 当前映射文件在第三张表中的外键名称 -->
<key column="userid"></key>
<!--class:角色实体类全路径
column:角色在第三张表中的外键名称 -->
<many-to-many class="cn.itcast.manytomany.Role" column="roleid"/>
</set>
</class>
</hibernate-mapping>
角色映射文件
<!-- 在角色里面表示所有用户,使用set标签 -->
<set name="setUser" table="user_role">
<!--角色在第三张表中的外键 -->
<key column="roleid"></key>
<many-to-many class="cn.itcast.manytomany.User" column="userid"/>
</set>
3. 核心配置文件中引入映射文件
<mapping resource="cn/itcast/manytomany/User.hbm.xml"/>
<mapping resource="cn/itcast/manytomany/Role.hbm.xml"/>
多对多级联保存
根据用户保存角色
1.在用户配置文件中使用set标签进行配置,cascade属性值为save-update
<!--name:实体类中的角色集合变量
table属性:第三张表的名称 -->
<set name="setRole" table="user_role" cascade="save-update,delete">
<!-- key标签里配置 当前映射文件在第三张表中的外键名称 -->
<key column="userid"></key>
<!--class:角色实体类全路径
column:角色在第三张表中的外键名称 -->
<many-to-many class="cn.itcast.manytomany.Role" column="roleid"/>
</set>
2.代码实现
创建用户和角色对象,只要把角色放到用户里面,最终保存用户就可以了
package cn.itcast.hibernatetest;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import cn.itcast.manytomany.Role;
import cn.itcast.manytomany.User;
import cn.itcast.utils.HibernateUtils;
public class HibernateManyToMany {
//演示多对多级联保存
public static void main(String[] args){
SessionFactory sessionFactory=null;
Session session=null;
Transaction tx=null;
try {
Configuration configuration = new Configuration();
configuration.configure();
sessionFactory = configuration.buildSessionFactory();
session=sessionFactory.openSession();
tx=session.beginTransaction();
//添加两个用户,为每个用户添加两个角色
//1创建对象
User user1=new User();
user1.setUser_name("lucy");
user1.setUser_password("123");
User user2=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("保安");
//建立关系,把角色放到用户里面
//user1--r1/r2
user1.getSetRole().add(r1);
user1.getSetRole().add(r2);
//user2--r2/r3
user2.getSetRole().add(r2);
user2.getSetRole().add(r3);
//保存用户
session.save(user1);
session.save(user2);
//提交事务
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
}finally {
//session.close();
//web项目sessionfactory不需要关闭
sessionFactory.close();
}
}
}
级联删除(了解)
1.在set标签里配置,cascade属性值为delete
<set name="setRole" table="user_role" cascade="save-update,delete">
2.删除用户
User user=session.get(User.class, 1);
session.delete(user);
维护第三张表
1.用户和角色是多对多,通过维护第三张表来维护他们的关系
2.让某个用户有某个角色
先根据id查询用户和角色,再把角色放到用户里
//让某个用户有某个角色
//让Lucy有经纪人角色
//查询Lucy和经纪人
User lucy=session .get(User.class, 1);
Role role=session.get(Role.class, 1);
//把角色放到set集合里面
lucy.getSetRole().add(role);
3.让某个用户没有某个角色
先根据id查询用户和角色,把用户里面的角色去掉remove
//让某个用户有某个角色
//让Lucy有经纪人角色
//查询Lucy和经纪人
User lucy=session .get(User.class, 1);
Role role=session.get(Role.class, 1);
lucy.getSetRole().remove(role);