主表:没有外键 有主键 从表:拥有外键的是从表 先操作从表,再去操作主表 one-to-one ,many-to-one 只是表达多个表之间的关系。 外键:目的是多表连接 主键:目的是唯一标识数据
示例: 一个人对应一个身份证 ,一夫一妻制, 一个萝卜一个坑。。。。
一对一的关系用程序如何描述:
示例:一夫一妻制
Husband.java
public class Husband{
private Integer marryId; //结婚编号
private String name; //名称
private Integer age; //年龄
private Integer hid; //丈夫的身份证号
private Wife wife; //丈夫和妻子有一对一的关系
set/get....
}
Wife.java
public class Wife{
private Integer marryId; //妻子的身份证号
private String name; //名称
private Integer age; //年龄
private Integer wid; //结婚编号
private Husband husband;//妻子和丈夫有一对一的关系
set/get....
}
用已有的主键充当外键去连接表来表示关系
元数据配置文件:
version="1.0" encoding="UTF-8"?>
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
package="com.qf.domain">
name="Husband" table="husband">
name="marryId">
class="native">
name="name">
name="age">
name="hid">
name="wife" constrained="true">
version="1.0" encoding="UTF-8"?>
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
package="com.qf.domain">
name="Wife" table="wife">
name="marryId">
class="native">
name="name">
name="age">
name="wid">
name="husband">
/**
* one-to-one表示一对一的关系。
* constrained="true"表示外键约束。当前类映射表的主键作为外键去连接另外一个表的主键。
* 示例: husband的主键作为外键去连接wife的主键。建立了一对一的关系(夫妻关系)。
*
* 主表 wife
* 副表(从表) husband 维护外键,通过外键去连接主表的主键
*
* 手动删除表的先删除副表。再删除主表。
*
* 方式一: 按照主键关系映射的(用已有的主键充当外键去连接关系) 上午重点:
* 方式二:按照外键关系映射的。(给表插入额外的一个列作为外键去连接另外一个表)
*/
@Test
public void test01() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
Husband husband =new Husband();
husband.setName("丈夫");
Wife wife =new Wife();
wife.setName("妻子");
//表达一对一的关系
husband.setWife(wife);
wife.setHusband(husband);
//有约束关系的表后插入(该表插入的时候要 找对应的关系的那条数据)
//先插入主表
session.save(wife);
//后插入副表
session.save(husband);
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}
给表额外插入一个列作为外键去连接另一个表
Wife.java
public class Wife{
private Integer wid; //妻子的身份证号(主键)
private String name; //名称
private Integer age; //年龄
private Integer marryId; //结婚编号
private Husband husband;//妻子和丈夫有一对一的关系
set/get....
}
Husband.java
public class Husband{
private Integer hid; //丈夫的身份证号 (主键)
private String name; //名称
private Integer age; //年龄
private Integer marryId; //结婚编号
private Wife wife; //丈夫和妻子有一对一的关系
set/get....
//理解: 多个表中主键都有各自的含义及内容的时候(主键不一样)
//给husband额外插入一个列wife_id1,作为外键去连接wife表
}
version="1.0" encoding="UTF-8"?>
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
package="com.qf.domain">
name="Husband" table="husband">
name="hid">
class="native">
name="name">
name="age">
name="marryId">
name="wife" unique="true" column="wife_id1">
version="1.0" encoding="UTF-8"?>
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
package="com.qf.domain">
name="Wife" table="wife">
name="wid">
class="native">
name="name">
name="age">
name="marryId">
name="husband">
@Test
public void test01() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
Husband husband =new Husband();
husband.setName("丈夫1");
Wife wife =new Wife();
wife.setName("妻子1");
//表达一对一的关系
husband.setWife(wife);
wife.setHusband(husband);
//有约束关系的表后插入(该表插入的时候要 找对应的关系的那条数据)
//先插入主表
session.save(wife);
//后插入副表
session.save(husband);
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}
示例:客户和联系人为例:
一对多: 一个客户对应多个联系人
多对一:多个联系人对应一个客户
package com.qf.domain;
//从表(拥有外键。)
public class Contact {
private Integer contact_id; //主键
private String contact_name;
private Integer contact_cust_id;//外键(表达关系的时候声明外键即可)
private String contact_gender;
private String contact_phone;
private String contact_mobile;
private String contact_email;
private String contact_qq;
private String contact_position;
private String contact_memo;//备注
//表达多(Contact)对一(Customer)关系
private Customer customer;
set/get.....
}
package com.qf.domain;
import java.util.HashSet;
import java.util.Set;
//主表
public class Customer {
private Integer cust_id;//主键
private String cust_name;
private Integer cust_user_id;
private Integer cust_create_id;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_linkman;
private String cust_phone;
private String cust_mobile;
//表达一(Customer)对多(Contact)的关系
private Set<Contact> contacts =new HashSet<>();
set/get.....
}
version="1.0" encoding="UTF-8"?>
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
package="com.qf.domain">
name="Contact" table="contact">
name="contact_id">
class="native">
name="contact_name" >
name="contact_gender" >
name="contact_phone" >
name="contact_mobile" >
name="contact_email" >
name="contact_qq" >
name="contact_position" >
name="contact_memo" >
name="customer" column="contact_cust_id">
version="1.0" encoding="UTF-8"?>
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
package="com.qf.domain">
name="Customer" table="customer">
name="cust_id" column="cust_id">
class="native">
name="cust_name" column="cust_name">
name="cust_user_id" column="cust_user_id">
name="cust_create_id" column="cust_create_id">
name="cust_source" column="cust_source">
name="cust_industry" column="cust_industry">
name="cust_level" column="cust_level">
name="cust_linkman" column="cust_linkman">
name="cust_phone" column="cust_phone">
name="cust_mobile" column="cust_mobile">
name="contacts">
column="contact_cust_id">
class="Contact"/>
version="1.0" encoding="UTF-8"?>
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
name="hibernate.connection.driver_class">com.mysql.jdbc.Driver
name="hibernate.connection.url">jdbc:mysql://localhost:3306/1715_hibernate05
name="hibernate.connection.username">root
name="hibernate.connection.password">123456
name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect
name="hibernate.show_sql">true
name="hibernate.format_sql">true
name="hibernate.hbm2ddl.auto">update
name="hibernate.connection.isolation">4
name="hibernate.current_session_context_class">thread
resource="com/qf/domain/Customer.hbm.xml"/>
resource="com/qf/domain/Contact.hbm.xml"/>
@Test
public void test001() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
//1个客户
Customer customer= new Customer();
customer.setCust_name("阿里巴巴");
//多个联系人,示例2个
Contact contact1 =new Contact();
contact1.setContact_name("马云");
Contact contact2 =new Contact();
contact2.setContact_name("李总");
//表达多表关系
//一对多
//把联系人给客户添加上
customer.getContacts().add(contact1);
customer.getContacts().add(contact2);
//多对一
contact1.setCustomer(customer);
contact2.setCustomer(customer);
//持久化保存
session.save(customer);
session.save(contact1);
session.save(contact2);
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}
//给指定客户添加新的联系
//持久态的对象会自动更新,已经在数据库中
//瞬时状态和游离状态必须通过方法转化成持久态才可以保存到数据
@Test
public void test002() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
//1.先找出客户
Customer customer = session.get(Customer.class, 1);
//2.新加联系人
Contact contact =new Contact();
contact.setContact_name("刘总");
//表达一对多的关系
customer.getContacts().add(contact);
//表达多对一的关系
contact.setCustomer(customer);
//保存
session.save(contact);
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}
示例1:多个学生可以被多个老师教,多个老师可以教多个 学生;
示例2:多个用户可以有多个角色,多个角色可以有多个用户。
例如:马云既是老板又是演员。李彦宏既是企业家又是老板。
public class User {
private Integer user_id;
private String user_name;
private String user_pwd;
private String user_state;//用户状态
//表达User和Role的多对多的关系
private Set<Role> roles =new HashSet<>();
set/get.......
}
public class Role {
private Integer role_id;//角色编号
private String role_name;//角色名
private String role_memo;//角色备注
//表达Role和User的多对多的关系
private Set<User> users =new HashSet<>();
set/get.......
}
version="1.0" encoding="UTF-8"?>
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
package="com.qf.domain">
name="User" table="user">
name="user_id">
class="native">
name="user_name">
name="user_pwd">
name="user_state">
name="roles" table="user_role" inverse="true" >
column="user_id1">
class="Role" column="role_id1">
version="1.0" encoding="UTF-8"?>
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
package="com.qf.domain">
name="Role" table="role">
name="role_id">
class="native">
name="role_name">
name="role_memo">
name="users" table="user_role" >
column="role_id1">
class="User" column="user_id1">
version="1.0" encoding="UTF-8"?>
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
name="hibernate.connection.driver_class">com.mysql.jdbc.Driver
name="hibernate.connection.url">jdbc:mysql://localhost:3306/1715_hibernate06
name="hibernate.connection.username">root
name="hibernate.connection.password">123456
name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect
name="hibernate.show_sql">true
name="hibernate.format_sql">true
name="hibernate.hbm2ddl.auto">update
name="hibernate.connection.isolation">4
name="hibernate.current_session_context_class">thread
resource="com/qf/domain/User.hbm.xml"/>
resource="com/qf/domain/Role.hbm.xml"/>
//插入
@Test
public void test01() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
User user1 =new User();
user1.setUser_name("马云11111");
User user2 =new User();
user2.setUser_name("李彦宏1111");
Role role1 =new Role();
role1.setRole_name("企业家11111");
Role role2 =new Role();
role2.setRole_name("演员11111");
//表达多对多的关系
//从user角度出发表达关系
user1.getRoles().add(role1);
user1.getRoles().add(role2);
user2.getRoles().add(role1);
user2.getRoles().add(role2);
//从role角度出发表达关系
role1.getUsers().add(user1);
role1.getUsers().add(user2);
role2.getUsers().add(user1);
role2.getUsers().add(user2);
session.save(user1);
session.save(user2);
session.save(role1);
session.save(role2);
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}
执行以上代码报错:约束异常。
解决方式一:去除掉一方关系表达维护,例如:删除掉30-34行代码
解决方式二:代码不用改变,在不需要维护关系的地方添加inverse="true"(谁放弃给谁加)
示例:User维护User和Role的关系。 Role放弃关系维护。
<set name="roles" table="user_role" inverse="true" >
<key column="user_id1">key>
<many-to-many class="Role" column="role_id1">many-to-many>
set>
备注:inverse
true:放弃维护关系
false:维护关系 ,默认
/* cascade:级联操作
* save-update(重点): 级联更新 .持久化当前对象的同时要持久化与之相关联的对象。
* 示例:session.save(User) 含义:持久化User的同时在持久化与User关联的类Role
在以上案例中可以去除40行和41行
* delete: 级联删除 删除一个对象的同时会删除掉与之相关连的对象 (不建议使用,慎重使用)
* all: save-update和delete结合一起
*/
//删除用户(使用cascade="delete"会删除调用当前数据和与之关联的所有数据)
@Test
public void test02() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
//删除一个用户
User user = session.get(User.class, 3);
session.delete(user);//删除user的同时删除了该user关联的role角色
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}
//给用户删除指定角色(不使用cascade="delete"删除)
@Test
public void test03() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
try {
//一个用户
User user = session.get(User.class, 5);
//给该用户删除一个角色
Role role= session.get(Role.class, 6);
//从用户移除角色
user.getRoles().remove(role);//内连接查询
session.delete(role);
transaction.commit();
} catch (Exception e) {
// TODO: handle exception
if (transaction!=null) {
transaction.rollback();
}
}
}