表与表之间的关系
一对多
通过外键建立关系
多对多
创建第三章表维护关系:表中至少有两个字段作为外键,指向两个表的主键
一对一
Hibernate一对多操作
一对多映射配置
第一步、创建实体类,如客户,联系人
public class Customer {
private Integer cid;
private String customerName;
private String customerSource;
private String customerLevel;
private String customerPhone;
private String customerEmail;
private String customerAddress;
// 在客户里表示多个联系人,一个客户有多个联系人
// hibernate要求用集合表示多的数据,使用set
private Set<LinkMan> set = new HashSet<LinkMan>();
public Set<LinkMan> getSet() {
return set;
}
public void setSet(Set<LinkMan> set) {
this.set = set;
}
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getCustomerSource() {
return customerSource;
}
public void setCustomerSource(String customerSource) {
this.customerSource = customerSource;
}
public String getCustomerLevel() {
return customerLevel;
}
public void setCustomerLevel(String customerLevel) {
this.customerLevel = customerLevel;
}
public String getCustomerPhone() {
return customerPhone;
}
public void setCustomerPhone(String customerPhone) {
this.customerPhone = customerPhone;
}
public String getCustomerEmail() {
return customerEmail;
}
public void setCustomerEmail(String customerEmail) {
this.customerEmail = customerEmail;
}
public String getCustomerAddress() {
return customerAddress;
}
public void setCustomerAddress(String customerAddress) {
this.customerAddress = customerAddress;
}
}
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) 在联系人实体类里面表示所属客户
第三步、配置映射关系
(1) 一个实体类一个映射文件
(2) 把映射最基本配置完成
(3) 在映射文件中,配置一对多关系
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- 1.配置类和表对应
name:实体类全路径
table:数据库表的名称
-->
<class name="com.bpf.entity.Customer" table="t_customer">
<id name="Cid" column="cid">
<generator class="native"></generator>
</id>
<property name="customerName" column="customerName"></property>
<property name="customerSource" column="customerSource"></property>
<property name="customerLevel" column="customerLevel"></property>
<property name="customerPhone" column="customerPhone"></property>
<property name="customerEmail" column="customerEmail"></property>
<property name="customerAddress" column="customerAddress"></property>
<!-- 表示所有联系人 -->
<set name="set" cascade="save-update,delete" inverse="true">
<key column="clid"></key>
<one-to-many class="com.bpf.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://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- 1.配置类和表对应
name:实体类全路径
table:数据库表的名称
-->
<class name="com.bpf.entity.LinkMan" table="t_linkMan">
<id name="lkm_id" column="lkm_id">
<generator class="native"></generator>
</id>
<!-- 3.其他属性和表字段对应 -->
<property name="lkm_name" column="lkm_name"></property>
<property name="lkm_gender" column="lkm_gender"></property>
<property name="lkm_phone" column="lkm_phone"></property>
<!-- 表示联系人所属的客户 -->
<many-to-one name="customer" class="com.bpf.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>
<!-- 1.配置数据库信息 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">yourURL</property>
<property name="hibernate.connection.username">username</property>
<property name="hibernate.connection.password">password</property>
<!-- 2.配置hibernate信息 (可选)-->
<!-- 输出底层sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 输出底层sql语句格式化 -->
<property name="hibernate.format_sql">true</property>
<!-- hibernate帮助创建表,需要配置 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!--配置数据库方言 (某数据库特有的语句)-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!--绑定session到本地线程 -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 3.把映射文件放到核心配置文件中 -->
<mapping resource="com/bpf/entity/Customer.hbm.xml"/>
<mapping resource="com/bpf/entity/LinkMan.hbm.xml"/>
<mapping resource="com/bpf/manytomany/User.hbm.xml"/>
<mapping resource="com/bpf/manytomany/Role.hbm.xml"/>
</session-factory>
</hibernate-configuration>
一对多级联操作
级联操作:
1、 级联保存
(1) 添加了一个客户,为这个客户添加多个联系人
2、 级联删除
(1) 删除某一个客户,这个客户里面所有的联系人也要删除
一对多级联保存
1、 为一个客户添加一个联系人
2、 复杂操作
public void testAddDemo1() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
// 添加一个客户,为这个客户添加一个联系人
Customer customer = new Customer();
customer.setCustomerName("asd");
customer.setCustomerLevel("vip");
customer.setCustomerSource("微信");
customer.setCustomerPhone("123456789");
customer.setCustomerEmail("1234567@qq.com");
customer.setCustomerAddress("china");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("大白一号");
linkMan.setLkm_gender("男");
linkMan.setLkm_phone("23451343");
// 在客户表示联系人,在联系人表示客户(建立客户与联系人的关系)
customer.getSet().add(linkMan);
linkMan.setCustomer(customer);
session.save(customer);
session.save(linkMan);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
3、 简化操作
(1) 在客户映射文件中配置(set标签中配置cascade属性)
<set name="set" cascade="save-update">
(2) 创建客户联系人对象,只需要把联系人放到客户中
public void testAddDemo2() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
// 添加一个客户,为这个客户添加一个联系人
Customer customer = new Customer();
customer.setCustomerName("白大侠");
customer.setCustomerLevel("vip");
customer.setCustomerSource("QQ");
customer.setCustomerPhone("2333333");
customer.setCustomerEmail("6666666@qq.com");
customer.setCustomerAddress("山西");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("大白二号");
linkMan.setLkm_gender("女");
linkMan.setLkm_phone("777");
// 在客户表示联系人,在联系人表示客户(建立客户与联系人的关系)
customer.getSet().add(linkMan);
session.save(customer);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
一对多级联删除
1、 删除某个客户,然后该客户的联系人也全部删除
2、 操作:
(1) 在客户的映射文件中的set标签进行配置
<set name="set" cascade="save-update,delete">
(2) 查询,删除
public void testDeleteDemo() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
//删除id为3的客户
Customer customer = session.get(Customer.class, 3);
session.delete(customer);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
3、 执行过程
(1) 根据id查客户
(2) 根据外键查联系人
(3) 将联系人外键设为null
(4) 删除客户以及对应联系人
一对多修改
1、 给联系人换一个客户
2、 Inverse属性
(1) Hibernate中双向维护外键,所以会修改两次外键,造成了性能问题
(2) 可以让其中一方不维护外键
一对多中,让一不维护外键
(3) 具体实现
映射文件配置,在set标签上使用inverse属性
<set name="set" cascade="save-update,delete" inverse="true">
public void testUpdateDemo() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 1);
LinkMan linkMan = session.get(LinkMan.class, 1);
customer.getSet().add(linkMan);
linkMan.setCustomer(customer);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
Hibernate多对多操作
映射配置
以用户和角色为例
1、 创建实体类,用户和角色
2、 让两个实体类互相表示
(1) 一个用户表示多个角色,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;
}
}
(2) 一个角色有多个用户,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;
}
}
3、 配置映射关系
(1) 基本配置
(2) 配置多对多
User:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- 1.配置类和表对应
name:实体类全路径
table:数据库表的名称
-->
<class name="com.bpf.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="setRole" table="user_role" cascade="save-update,delete">
<!-- key:当前映射文件在第三张表的外键名称 -->
<key column="userId"></key>
<many-to-many class="com.bpf.manytomany.Role" column="roleId"></many-to-many>
</set>
</class>
</hibernate-mapping>
Role:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- 1.配置类和表对应
name:实体类全路径
table:数据库表的名称
-->
<class name="com.bpf.manytomany.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 name="setUser" table="user_role">
<key column="roleId"></key>
<many-to-many class="com.bpf.manytomany.User" column="userId"></many-to-many>
</set>
</class>
</hibernate-mapping>
4、 在核心配置文件中引入映射文件
<?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>
<!-- 1.配置数据库信息 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate_day03</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">bestbpf7748</property>
<!-- 2.配置hibernate信息 (可选)-->
<!-- 输出底层sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 输出底层sql语句格式化 -->
<property name="hibernate.format_sql">true</property>
<!-- hibernate帮助创建表,需要配置 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!--配置数据库方言 (某数据库特有的语句)-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!--绑定session到本地线程 -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 3.把映射文件放到核心配置文件中 -->
<mapping resource="com/bpf/entity/Customer.hbm.xml"/>
<mapping resource="com/bpf/entity/LinkMan.hbm.xml"/>
<mapping resource="com/bpf/manytomany/User.hbm.xml"/>
<mapping resource="com/bpf/manytomany/Role.hbm.xml"/>
</session-factory>
</hibernate-configuration>
级联保存
根据用户保存角色
1、 在用户配置文件中set标签进行设置(上已展示)
2、 将角色对象放入用户对象中,然后保存用户
public void testSave() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
// 添加两个用户,为每个用户添加两个角色
User user1 = new User();
user1.setUser_name("皮皮马");
user1.setUser_password("2345");
User user2 = new User();
user2.setUser_name("孙悟空");
user2.setUser_password("3456");
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/r3; user2---r2/r3
user1.getSetRole().add(r1);
user1.getSetRole().add(r3);
user2.getSetRole().add(r2);
user2.getSetRole().add(r3);
session.save(user1);
session.save(user2);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.clear();
session.close();
sessionFactory.close();
}
}
级联删除
1、 在set标签配置
2、 删除用户
// 级联删除会删除所有相关角色,不管该角色是否被其他用户使用,一般不使用
@Test
public void testDelete() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
User sun = session.get(User.class, 2);
session.delete(sun);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
维护第三张表
1、 用户和角色是多对多关系,维护关系是通过第三章表
2、 让某个用户有某个角色
public void testMaintenance1() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
// 为用户皮皮马添加角色“大侠”
User bpf = session.get(User.class, 1);
Role swordsman = session.get(Role.class, 2);
bpf.getSetRole().add(swordsman);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.close();
sessionFactory.close();
}
}
3、 让某个用户没有某个角色
public void testMaintenance2() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try {
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
// 为用户皮皮马删除角色“大侠”
User bpf = session.get(User.class, 1);
Role swordsman = session.get(Role.class, 2);
bpf.getSetRole().remove(swordsman);
transaction.commit();
} catch (Exception e) {
transaction.rollback();
} finally {
session.close();
sessionFactory.close();
}
}