文章目录
实体一对多关联
例如部门与职工之间的关系,就是一对多
购物网站,用户与订单之间关系就是一对多
第一种存储多个对象的类型是Set类型。
数据库一对多关联
Set属性方式实现一对多
保存时候会执行三次SQL语句,插入一,插入多,更新多的外键。
注意,在数据库这里,一对应的没有外键,是被外键的,但是多有外键,是主动外键别人的。
但是在Java代码这里是反过来的,一有多的引用。
项目结构
order.java
package com.hibernate.entity;
public class Order {
private Integer id;
private Double price;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Order [id=" + id + ", price=" + price + "]";
}
}
user.java
package com.hibernate.entity;
import java.util.HashSet;
import java.util.Set;
public class User {
private Integer id;
private String userName;
private String password;
//域模型中用来表示从用户能够导航到订单数据(从用户到订单的一对多关联)
//先初始化是为了放置空引用异常
//Set类型无序,且不重复。
//要求有顺序的话还是用
private Set orderSet = new HashSet<>();
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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [id=" + id + ", userName=" + userName + ", password=" + password + "]";
}
public Set getOrderSet() {
return orderSet;
}
public void setOrderSet(Set orderSet) {
this.orderSet = orderSet;
}
}
order.hbm.xml
<?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 package="com.hibernate.entity">
<class name="Order" table="hibernate_05_01_orders">
<id name="id" type="int" column="id">
<generator class="identity"></generator>
</id>
<property name="price" column="price" ></property>
</class>
</hibernate-mapping>
user.hbm.xml
<?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 package="com.hibernate.entity">
<class name="User" table="hibernate_05_01_user">
<id name="id" type="int" column="id">
<generator class="identity"/>
</id>
<property name="userName" type="java.lang.String" column="name"/>
<property name="password" type="java.lang.String" column="password"/>
<!-- 映射User与Order之间的一对多关系
set标签用来映射Set类型的属性(name)
key:指定外键字段名字(此名称是数据库库名称)
one-to-many表示一对多关系 -->
<!-- 用户与订单这种情况不会产生创建用户也创建订单,
删除订单也不会删除用户,所以进选择delete -->
<set name="orderSet" cascade="delete">
<key column="USER_ID"/>
<one-to-many class="Order"/>
</set>
</class>
</hibernate-mapping>
Test.java
package com.hibernate.ui;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hibernate.entity.Order;
import com.hibernate.entity.User;
import com.hibernate.util.HibernateUtil;
public class Test {
public static void main(String[] args) {
saveUserAndOrder();
// addOrder();
// getUserAndOrders();
// deleteUser();
HibernateUtil.closeSessionFactory();
}
//保存
private static void saveUserAndOrder() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
User u = new User();
u.setUserName("李四");
u.setPassword("77777");
Order o = new Order();
o.setPrice(300.0);
//建立关联
Set set = new HashSet();
set.add(o);
u.setOrderSet(set);
session.save(u);
session.save(o);
tx.commit();
session.close();
}
//给已经存在的用户添加新的订单
private static void addOrder() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
User u = session.get(User.class, new Integer(1));
//新的订单对象
Order o = new Order();
o.setPrice(200.0);
//建立关联
u.getOrderSet().add(o);
session.save(o);
tx.commit();
session.close();
}
//一对一关联式,查询用户也会查询订单
//一对多时候查询用户仅是用户
//检索用户数据,并通过用户导航到它所关联的订单
private static void getUserAndOrders() {
Session session = HibernateUtil.openSession();
//一对多关联映射默认情况下查询用户时,不会连接订单表查询
User u = session.get(User.class, new Integer(1));
//通过上述用户对象导航到它关联的订单(映射关联关系的优势)
//这个方法也会触发一次查询
System.out.println(u.getOrderSet());
session.close();
}
//由于配置了级联删除操作,所以删除用户时,会自动删除同用户关联的订单
private static void deleteUser() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
User u = session.get(User.class, new Integer(1));
session.delete(u);
tx.commit();
session.close();
}
}
hibernate.cfg.xml
<?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就是一个配置项 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- dialect是方言,表明用的是什么数据库方言 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库驱动类,指定类名 -->
<!-- 下面是链接数据库的信息,和JDBC类似 -->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate-database?useUicode=true&characterEncoding=UTF-8</property>
<!-- & 是转义字符,此处是转义分号所用-->
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></property>
<!-- 上面5个配置项是必选的,下面两个是可选的,分别是打印sql语句与格式化sql语句,便于调试-->
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<!-- 设置映射文件,属性值是包名+文件名,注意格式变化,点变成了斜杠-->
<mapping resource="com/hibernate/entity/Order.hbm.xml"/>
<mapping resource="com/hibernate/entity/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
User.MySql
orders.MySql
List属性实现一对多关联
项目结构
order.java
package com.hibernate.entity;
public class Order {
private Integer id;
private Double price;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
public String toString() {
return "Order [id=" + id + ", price=" + price + "]";
}
}
user.java
package com.hibernate.entity;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class User {
private Integer id;
private String userName;
private String password;
//域模型中用来表示从用户能够导航到订单数据(从用户到订单的一对多关联)
//先初始化是为了防止空引用异常
//Set类型无序,且不重复。
//要求有顺序的话还是用
private List orderList = new ArrayList<>();
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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [id=" + id + ", userName=" + userName + ", password=" + password + "]";
}
public List getOrderList() {
return orderList;
}
public void setOrderList(List orderList) {
this.orderList = orderList;
}
}
order.hbm.xml
<?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 package="com.hibernate.entity">
<class name="Order" table="hibernate_05_02_orders">
<id name="id" type="int" column="id">
<generator class="identity"></generator>
</id>
<property name="price" column="price" ></property>
</class>
</hibernate-mapping>
user.hbm.xml
<?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 package="com.hibernate.entity">
<class name="User" table="hibernate_05_02_user">
<id name="id" type="int" column="id">
<generator class="identity"/>
</id>
<property name="userName" type="java.lang.String" column="name"/>
<property name="password" type="java.lang.String" column="password"/>
<!-- 映射User与Order之间的一对多关系
List标签用来映射List类型的属性(name)
key:指定外键字段名字(此名称是数据库库名称)
index=保存插入顺序的字段
one-to-many表示一对多关系 -->
<list name="orderList" cascade="delete">
<key column="USER_ID"/>
<index column="index11"/>
<one-to-many class="Order"/>
</list>
</class>
</hibernate-mapping>
Test.java
package com.hibernate.ui;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hibernate.entity.Order;
import com.hibernate.entity.User;
import com.hibernate.util.HibernateUtil;
public class Test {
public static void main(String[] args) {
// saveUserAndOrder();
addOrder();
// getUserAndOrders();
// deleteUser();
HibernateUtil.closeSessionFactory();
}
//保存
private static void saveUserAndOrder() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
User u = new User();
u.setUserName("李四");
u.setPassword("77777");
Order o = new Order();
o.setPrice(300.0);
//建立关联
u.getOrderList().add(o);
session.save(u);
session.save(o);
tx.commit();
session.close();
}
//给已经存在的用户添加新的订单
private static void addOrder() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
User u = session.get(User.class, new Integer(3));
System.out.println(u.toString());
//新的订单对象
Order o = new Order();
o.setPrice(100.0);
//建立关联
u.getOrderList().add(o);
session.save(o);
tx.commit();
session.close();
}
//检索用户数据,并通过用户导航到它所关联的订单
private static void getUserAndOrders() {
Session session = HibernateUtil.openSession();
//一对多关联映射默认情况下查询用户时,不会连接订单表查询
User u = session.get(User.class, new Integer(109));
//通过上述用户对象导航到它关联的订单(映射关联关系的优势)
System.out.println(u.getOrderList());
session.close();
}
//由于配置了级联删除操作,所以删除用户时,会自动删除同用户关联的订单
private static void deleteUser() {
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
User u = session.get(User.class, new Integer(109));
session.delete(u);
tx.commit();
session.close();
}
}
user.MySql
orders.MySql
Map属性配置方式
项目结构
user.java
package com.hibernate.entity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class User {
private Integer id;
private String userName;
private String password;
//域模型中用来表示从用户能够导航到订单数据(从用户到订单的一对多关联)
//key - value 类型
private Map<String,Order> orderMap = new HashMap<>();
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 String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [id=" + id + ", userName=" + userName + ", password=" + password + "]";
}
public Map<String,Order> getOrderMap() {
return orderMap;
}
public void setOrderMap(Map<String,Order> orderMap) {
this.orderMap = orderMap;
}
}
user.hbm.xml
<?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 package="com.hibernate.entity">
<class name="User" table="hibernate_05_03_user">
<id name="id" type="int" column="id">
<generator class="identity"/>
</id>
<property name="userName" type="java.lang.String" column="name"/>
<property name="password" type="java.lang.String" column="password"/>
<!-- 映射User与Order之间的一对多关系
map用来映射Map类型的属性
key:指定外键字段名字
index:指定保存Map中key值的字段
one-to-many表示一对多关系 -->
<map name="orderMap" cascade="delete">
<key column="USER_ID"/>
<index column="ORDER_KEY" type="string"></index>
<!-- string时hibernate定义的数据类型 -->
<one-to-many class="Order"/>
</map>
</class>
</hibernate-mapping>