一:一对多关联概念
1.实体一对多关联(1:n)
定义:
如果对于实体集A中的每一个实体,实体集B中有n个实体(n>=0)与之联系,反之,对于实体集B中的每一个实体,实体集A中至多只有一个实体与之联系,则称实体集A与实体集B有一对多联系,记为1:n。
实例:一个班级中有若干名学生,每个学生只在一个班级中学习。
示例:在一些购物网站中,用户和订单之间的关系就是一对多关联关系(一个用户可以有多个订单,而一个订单只属于一个用户。)
2.数据库一对多关联
- 在关系模型中,只存在外键参照关系,而且是many方参照one方。
二:Hibernate实现单向一对多关联
引例:
通常情况下,在一些购物网站系统中,用户和订单之间的关系就是一对多关联关系,并且对于用户来说需要知道自己有哪些订单,对于商家来说需要知道某个订单属于哪个用户,思考这种情况该如何实现?
1.xml配置实现
用户类:
public class User { private int id; private String userName; private String passWord; private Set<Order> orders = new HashSet<>(); public int getId() { return id; } public void setId(int 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; } public Set<Order> getOrders() { return orders; } public void setOrders(Set<Order> orders) { this.orders = orders; } @Override public String toString() { return "User [id=" + id + ", userName=" + userName + ", passWord=" + passWord + ", orders=" + orders + "]"; } }
用户配置文件:
<?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="user"> <id name="id" type="int"> <column name="id"></column> <generator class="native"></generator> </id> <property name="userName" column="user_name" type="java.lang.String"> </property> <property name="passWord" column="password" type="java.lang.String" /> <set name="orders" cascade="all"> <key column="user_id"></key> <one-to-many class="Order" /> </set> </class> </hibernate-mapping>
订单类:
public class Order { private int id; private int price; public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Order [id=" + id + ", price=" + price + ", getId()=" + getId() + ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]"; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } }
订单配置文件:
<?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="n_order"> <id name="id" type="int"> <column name="id"></column> <generator class="increment"></generator> </id> <property name="price"></property> </class> </hibernate-mapping>
测试类:
public class Test { public static void main(String[] args) { // 保存用户 // saveUser(); // 保存订单 // saveOrders(); // 根据用户查找订单 // findOrderByUserId(); // 根据用户id删除订单 deleteOrderByUserId(); } public static void saveUser() { // 1.获取session对象 Session session = HibernateUtil.openSession(); Transaction tx = session.beginTransaction(); User user = new User(); user.setUserName("张三"); user.setPassWord("123"); session.save(user); tx.commit(); session.close(); // 5.关闭sessionFactory } public static void saveOrders() { // 1.获取session对象 Session session = HibernateUtil.openSession(); Transaction tx = session.beginTransaction(); User user = session.get(User.class, new Integer(1)); Set<Order> orders = user.getOrders(); for (int i = 0; i < 3; i++) { Order order = new Order(); order.setPrice(35); orders.add(order); } user.setOrders(orders); session.save(user); tx.commit(); session.close(); // 5.关闭sessionFactory } public static void findOrderByUserId() { Session session = HibernateUtil.openSession(); Transaction tx = session.beginTransaction(); User user = session.get(User.class, new Integer(1)); System.out.println(user.toString()); tx.commit(); session.close(); // 5.关闭sessionFactory } public static void deleteOrderByUserId() { Session session = HibernateUtil.openSession(); Transaction tx = session.beginTransaction(); User user = session.get(User.class, new Integer(1)); session.delete(user); tx.commit(); session.close(); // 5.关闭sessionFactory } }
当使用list集合映射时,需要在order表中添加一个额外字段来表示插入顺序
配置文件:
<?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="user"> <id name="id" type="int"> <column name="id"></column> <generator class="native"></generator> </id> <property name="userName" column="user_name" type="java.lang.String"> </property> <property name="passWord" column="password" type="java.lang.String" /> <list name="orders" cascade="all"> <key column="user_id"></key> <index column="order_index"></index> <one-to-many class="Order" /> </list> </class> </hibernate-mapping>
当使用Map集合映射时,需要在Order表中添加也给额外字段来记录Map中key的值
映射配置文件:
<?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="user"> <id name="id" type="int"> <column name="id"></column> <generator class="native"></generator> </id> <property name="userName" column="user_name" type="java.lang.String"> </property> <property name="passWord" column="password" type="java.lang.String" /> <map name="orders" cascade="all"> <key column="user_id"></key> <index column="order_key" type="string"></index> <one-to-many class="Order" /> </map> </class> </hibernate-mapping>
二:Hibernate双向一对多关联
目的:通过用户可以找到订单,通过订单也可以找到用户
1.使用xml文件方式完成配置
数据库表结构同上,只是配置文件发生改变
User类:
public class User { private int id; private String userName; private String passWord; private Map<String, Order> orders = new HashMap<>(); public int getId() { return id; } public void setId(int 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; } public Map<String, Order> getOrders() { return orders; } public void setOrders(Map<String, Order> orders) { this.orders = orders; } @Override public String toString() { return "User [id=" + id + ", userName=" + userName + ", passWord=" + passWord + ", orders=" + orders + "]"; } }
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 package="com.hibernate.entity"> <class name="User" table="user"> <id name="id" type="int"> <column name="id"></column> <generator class="native"></generator> </id> <property name="userName" column="user_name" type="java.lang.String"> </property> <property name="passWord" column="password" type="java.lang.String" /> <map name="orders" cascade="all"> <key column="user_id"></key> <index column="order_key" type="string"></index> <one-to-many class="Order" /> </map> </class> </hibernate-mapping>
Order类:
public class Order { private int id; private int price; private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Order [id=" + id + ", price=" + price + ", getId()=" + getId() + ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]"; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } }
Order类配置文件:
<?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="n_order2"> <id name="id" type="int"> <column name="id"></column> <generator class="increment"></generator> </id> <property name="price"></property> <many-to-one name="user" column="user_id" class="User"></many-to-one> </class> </hibernate-mapping>
2.使用注解方式完成配置
User类:
@Entity @Table(name = "user") public class User { private int id; private String userName; private String passWord; private Map<String, Order> orders = new HashMap<>(); @Id @GeneratedValue(generator = "nat") @GenericGenerator(name = "nat", strategy = "native") public int getId() { return id; } public void setId(int id) { this.id = id; } @Column(name = "user_name") 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; } @OneToMany(mappedBy = "user", targetEntity = Order.class, cascade = CascadeType.ALL) @MapKeyColumn(name = "order_key") public Map<String, Order> getOrders() { return orders; } public void setOrders(Map<String, Order> orders) { this.orders = orders; } @Override public String toString() { return "User [id=" + id + ", userName=" + userName + ", passWord=" + passWord + ", orders=" + orders + "]"; } }
Order类:
@Entity @Table(name = "n_order2") public class Order { private int id; private int price; private User user; @ManyToOne @JoinColumn(name = "user_id") public User getUser() { return user; } public void setUser(User user) { this.user = user; } @Id @GeneratedValue(generator = "nat") @GenericGenerator(name = "nat", strategy = "native") public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Order [id=" + id + ", price=" + price + ", getId()=" + getId() + ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]"; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } }