一、单向一对多:
一个用户可以有多个电话号码。站在用户的角度想就是用户是一的一方,他可以拥有多个电话号码,所以电话号码就是多的一方。通过这一个用户我们就可以查询到他有多少个电话号码。
1.1、先建一个电话号码的实体类。包含id、号码、和归属地三个字段。并给予get、set方法。
package cn.otote.entity;
public class Phone {
private Integer id;
private String phoneNumber;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Phone [id=" + id + ", phoneNumber=" + phoneNumber + ", address=" + address + "]";
}
}
1.2、因为要从用户这一方找到电话号码多的一方的信息。所以要在用户实体类放置一个set集合用来存放电话号码。
package cn.otote.entity;
import java.util.Set;
public class User {
private Integer id;
private String userName;
private Integer age;
private String sex;
private Set<Phone> phoneSet;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Set<Phone> getPhoneSet() {
return phoneSet;
}
public void setPhoneSet(Set<Phone> phoneSet) {
this.phoneSet = phoneSet;
}
@Override
public String toString() {
return "User [id=" + id + ", userName=" + userName + ", age=" + age + ", sex=" + sex + ", phoneSet=" + phoneSet
+ "]";
}
}
1.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">
<!-- package为实体类所在的包名 -->
<hibernate-mapping package="cn.otote.entity">
<!-- name="User"为User实体类的类名 table为User实体类在数据库中的表名 这里表名取为t_user -->
<class name="User" table="t_user" >
<!-- 主键用<id>标签 name为实体类中主键的属性名id column为t_user表中主键名id -->
<id name="id" column="id">
<!-- class="native"将主键id设为自增 -->
<generator class="native"/>
</id>
<!-- 普通字段用property标签 -->
<!-- name为实体类的属性名 column为表中的字段名 -->
<property name="userName" column="user_name"></property>
<!-- age属性与表中字段都为age 可以不用写column 以下同 -->
<property name="age"></property>
<property name="sex"></property>
<!-- 一对多的关键 用set标签来配置用户实体类中存放电话号码的集合 name为集合变量名-->
<!-- cascade="save-update"设置级联 保存一的一方的时候自动保存多的一方 -->
<set name="phoneSet" cascade="save-update">
<!-- key标签用来配置外键名 user_id表示多的一方外键名 -->
<key column="user_id"></key>
<!-- 一对多 class为电话号码的实体类类名 -->
<one-to-many class="Phone"/>
</set>
</class>
</hibernate-mapping>
1.4、配置电话号码的映射文件。
<?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">
<!-- package为实体类所在的包名 -->
<hibernate-mapping package="cn.otote.entity">
<class name="Phone" table="t_phone" >
<!-- 主键用<id>标签 name为实体类中主键的属性名id column为t_user表中主键名id -->
<id name="id" column="id">
<!-- class="native"将主键id设为自增 -->
<generator class="native"/>
</id>
<property name="phoneNumber"></property>
<property name="address"></property>
</class>
</hibernate-mapping>
1.5、在hibernate.cfg.xml中将Phone的映射文件加入。
<mapping resource="cn/otote/entity/Phone.hbm.xml" />
1.6、测试
@Test
void test() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
//先创建两个电话号码
Phone phone1=new Phone();
phone1.setPhoneNumber("110");
phone1.setAddress("北京");
Phone phone2=new Phone();
phone2.setPhoneNumber("119");
phone2.setAddress("深圳");
//创建一个用户 因为数据库中已经有用户了 所以直接拿一个
User user = (User) session.get(User.class, 1);
user.setPhoneSet(new HashSet<Phone>());
//维护关系 将两个电话号码添加到用户保存电话号码的集合中
user.getPhoneSet().add(phone1);
user.getPhoneSet().add(phone2);
//cascade="save-update"设置级联 保存一的一方的时候自动保存多的一方
//由于在用户的映射文件设置了级联 所以只需要保存一的一方(也就是用户这一方)多的一方会自动保存
session.save(user);
transaction.commit();
}
运行完接着打开数据库可以发现hibernate自动帮我们创建了一个电话号码表。并设置好了外键。而且我们刚才插入的两个电话号码也已经保存起来了。


接着测试下能否通过一个用户得知该用户所有的电话号码。
@Test
void test2() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
//获取id为1的用户
User user = (User) session.get(User.class, 1);
//打印用户信息 用户实体类中已经重写了tostring方法
System.out.println(user);
transaction.commit();
}

通过控制台信息可以发现可以通过一个用户得知该用户的所有电话号码。
二、单向多对一:
单项多对一跟一对多相反,通过多的这一方可以得知该条数据是属于哪个一的一方。也就是根据电话号码可以得知该电话号码是属于谁的。
2.1、因为hibernate是面对对象操作的,所以要在Phone这个类中加一个User属性用来存放用户。并给定get、set方法。这里User的变量名取为user。Phone实体类代码跟上方一样,只是多了个User属性。
2.2、配置Phone的映射表.
<?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">
<!-- package为实体类所在的包名 -->
<hibernate-mapping package="cn.otote.entity">
<class name="Phone" table="t_phone" >
<!-- 主键用<id>标签 name为实体类中主键的属性名id column为t_user表中主键名id -->
<id name="id" column="id">
<!-- class="native"将主键id设为自增 -->
<generator class="native"/>
</id>
<property name="phoneNumber"></property>
<property name="address"></property>
<!-- 配置多对一 name为Phone实体类中存放User的变量名 column为外键名 -->
<many-to-one name="user" column="user_id"></many-to-one>
</class>
</hibernate-mapping>
2.3、测试多对一:
@Test
void test3() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
//获取一个电话号码 数据库中电话号码id为5所以这里取5
Phone phone = (Phone) session.get(Phone.class, 5);
//打印电话号码信息 需要注意的是前面一对多的时候User类的tostring方法调用了Phone的tostring 所以测试的时候要把User中tostring的电话号码集合去掉,不然会出现栈溢出
System.out.println(phone);
transaction.commit();
}

通过控制台可以发现可以通过多的一方获取一的一方的信息。
三、双向一对多:
双向一对多也可以叫做双向多对一。就是将前面两个结合起来。在一个一方放置一个set集合来存放多的一方,在多的一放放置一个一的一方的对象用来存放一的一方的信息。
3.1、配置一的一方的映射文件:
<?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">
<!-- package为实体类所在的包名 -->
<hibernate-mapping package="cn.otote.entity">
<!-- name="User"为User实体类的类名 table为User实体类在数据库中的表名 这里表名取为t_user -->
<class name="User" table="t_user" >
<!-- 主键用<id>标签 name为实体类中主键的属性名id column为t_user表中主键名id -->
<id name="id" column="id">
<!-- class="native"将主键id设为自增 -->
<generator class="native"/>
</id>
<!-- 普通字段用property标签 -->
<!-- name为实体类的属性名 column为表中的字段名 -->
<property name="userName" column="user_name"></property>
<!-- age属性与表中字段都为age 可以不用写column 以下同 -->
<property name="age"></property>
<property name="sex"></property>
<!-- 一对多的关键 用set标签来配置用户实体类中存放电话号码的集合 name为集合变量名-->
<!-- cascade="save-update"设置级联 保存一的一方的时候自动保存多的一方 -->
<set name="phoneSet" cascade="save-update">
<!-- key标签用来配置外键名 user_id表示多的一方外键名 -->
<key column="user_id"></key>
<!-- 一对多 class为电话号码的实体类类名 -->
<one-to-many class="Phone"/>
</set>
</class>
</hibernate-mapping>
3.2、配置多的一方的映射文件:
<?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">
<!-- package为实体类所在的包名 -->
<hibernate-mapping package="cn.otote.entity">
<class name="Phone" table="t_phone" >
<!-- 主键用<id>标签 name为实体类中主键的属性名id column为t_user表中主键名id -->
<id name="id" column="id">
<!-- class="native"将主键id设为自增 -->
<generator class="native"/>
</id>
<property name="phoneNumber"></property>
<property name="address"></property>
<!-- 配置多对一 name为Phone实体类中存放User的变量名 column为外键名 -->
<many-to-one name="user" column="user_id"></many-to-one>
</class>
</hibernate-mapping>
3.3、测试:
此时已经完成双向一对多的配置,既可以通过一的一方得到多的一方,也可以通过多的一方得到一的一方。
@Test
void test4() {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
Transaction transaction = session.beginTransaction();
//通过user获取用户的所有电话
User user=(User) session.get(User.class, 1);
Set<Phone> phoneSet = user.getPhoneSet();
for (Phone phone : phoneSet) {
System.out.println(user.getUserName()+":"+phone.getPhoneNumber());
}
System.out.println("----------------");
//通过电话获取所属用户
Phone phone=(Phone) session.get(Phone.class,6);
System.out.println(phone.getPhoneNumber()+":"+phone.getUser().getUserName());
transaction.commit();
}


2025

被折叠的 条评论
为什么被折叠?



