用了一天整理下来。所有关系分为以下七种:
单向【1-1】
双向【1-1】
单向【1-N】
双向【1-N】
单向【N-1】
单向【N-N】
双向【N-N】
1单向【1-1】
基于外键的单向【1-1】是【N-1】的特殊形式,要求【N】方唯一。
基于外键的单向1-1只需要在原有的<many-to-one>元素增加unique=true属性,用以表示N的一端必须唯一
===》将单向【N-1】变为基于外键的单向【1-1】关联关系。
package OneToOneSingle; public class User { private Integer Userid; private String username; private String password; private UserInfo userinfo; public Integer getUserid() { return Userid; } public void setUserid(Integer userid) { Userid = userid; } 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 UserInfo getUserinfo() { return userinfo; } public void setUserinfo(UserInfo userinfo) { this.userinfo = userinfo; } }
package OneToOneSingle; public class UserInfo { private Integer InfoId; private String address; private String mail; public Integer getInfoId() { return InfoId; } public void setInfoId(Integer infoId) { InfoId = infoId; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getMail() { return mail; } public void setMail(String mail) { this.mail = mail; } }
<?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> <class name="OneToOneSingle.User" table="User"> <id name="Userid"> <generator class="native"></generator> </id> <property name="username" /> <property name="password"></property> <many-to-one name="userinfo" class="OneToOneSingle.UserInfo" column="info_id" unique="true" cascade="all" /> <!-- cascade为操作user对象时,同时联级保存 userinfo对象--> </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> <class name="OneToOneSingle.UserInfo" table="userInfo"> <!-- 主键对应 --> <id name="InfoId"> <generator class="native"></generator> </id> <property name="address" /> <property name="mail"></property> </class> </hibernate-mapping>
2双向【1-1】
基于主键的双向【1-1】两个关联表使用相同的主键值,其中一个表的主键共享另外一个表的主键。
使用标签<one-to-one>
constrained放错位置会导致外键死锁。
package OneToOneDouble; public class Husband { private Integer Id; private String husbanName; private Wife wife; public Integer getId() { return Id; } public void setId(Integer id) { Id = id; } public String getHusbanName() { return husbanName; } public void setHusbanName(String husbanName) { this.husbanName = husbanName; } public Wife getWife() { return wife; } public void setWife(Wife wife) { this.wife = wife; } }
package OneToOneDouble; public class Wife { private Integer Id; private String wifeName; private Husband husband; public Integer getId() { return Id; } public void setId(Integer id) { Id = id; } public String getWifeName() { return wifeName; } public void setWifeName(String wifeName) { this.wifeName = wifeName; } public Husband getHusband() { return husband; } public void setHusband(Husband husband) { this.husband = husband; } }
<?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> <class name="OneToOneDouble.Husband" table="husband"> <id name="Id"> <!-- 主键来源wife,也就是共享的主键 --> <generator class="foreign"> <param name="property">wife</param> </generator> </id> <property name="husbanName" /> <!-- constrained放错位置会导致外键死锁 --> <one-to-one name="wife" class="OneToOneDouble.Wife" constrained="true"/> </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> <class name="OneToOneDouble.Wife" table="wife"> <id name="Id"> <generator class="native"></generator> </id> <property name="wifeName" /> <one-to-one name="husband" class="OneToOneDouble.Husband" ></one-to-one> </class> </hibernate-mapping>
3单向【1-N】
从N-1反过来,由Teacher对象维护多个Student对象的管理。
只需要在【1】方添加对【N】方Set集合类型属性为Student的哈希set集合。
但是【不需要!】在【N】方定义Teacher属性。
外键依然是属于【N】方的。在持久化类中通过重写hashCode和equals方法来实现对持久化对象的比较,如果两个对象的标识符相等即对应数据库同一条记录,
那么Hibernate就会把两个对象看作同一个对象。
package OneToManySingle; public class Student { private String studentName; private Integer studentId; private String studentSex; public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public Integer getStudentId() { return studentId; } public void setStudentId(Integer studentId) { this.studentId = studentId; } public String getStudentSex() { return studentSex; } public void setStudentSex(String studentSex) { this.studentSex = studentSex; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((studentId == null) ? 0 : studentId.hashCode()); return result; } public Student() { // TODO Auto-generated constructor stub } }
package OneToManySingle; import java.util.HashSet; import java.util.Set; public class Teacher { private Integer teacherId; private String teacherName; private Integer teacherAge; private Set<Student> students = new HashSet<Student>(); public Integer getTeacherId() { return teacherId; } public void setTeacherId(Integer teacherId) { this.teacherId = teacherId; } public String getTeacherName() { return teacherName; } public void setTeacherName(String teacherName) { this.teacherName = teacherName; } public Integer getTeacherAge() { return teacherAge; } public void setTeacherAge(Integer teacherAge) { this.teacherAge = teacherAge; } public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } }
<?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"> <!-- javabean与表的映射关系 --> <hibernate-mapping> <class name="OneToManySingle.Student" table="student"> <!-- 主键对应 --> <id name="studentId"> <generator class="native"></generator> </id> <property name="studentName" /> <property name="studentSex"></property> </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"> <!-- javabean与表的映射关系 --> <hibernate-mapping> <class name="OneToManySingle.Teacher" table="teacher"> <!-- 主键对应 --> <id name="teacherId"> <generator class="native"></generator> </id> <property name="teacherName" /> <property name="teacherAge"></property> <set name="students"> <key column="teache_id"></key><!-- 外键 --> <one-to-many class="OneToManySingle.Student"/> </set> </class> </hibernate-mapping>
4双向【1-N】
就是【单向1-N】和【单向N-1】的整合。
【N】方存在【1】方属性,【1】放存放【N】方的set集合。
在实际开发中经常使用。
package OneToManyDouble; import java.util.HashSet; import java.util.Set; /*与Linkman建立一对多关系. * 一个客户可以有多个联系人 * linkman表的外键是cus_id; * */ public class Customer { private Integer cus_id; private String cus_name; private String cus_phone; private Set<Linkman> linkmans = new HashSet<Linkman>(); public Set<Linkman> getLinkmans() { return linkmans; } public void setLinkmans(Set<Linkman> linkmans) { this.linkmans = linkmans; } public Integer getCus_id() { return cus_id; } public void setCus_id(Integer cus_id) { this.cus_id = cus_id; } public String getCus_name() { return cus_name; } public void setCus_name(String cus_name) { this.cus_name = cus_name; } public String getCus_phone() { return cus_phone; } public void setCus_phone(String cus_phone) { this.cus_phone = cus_phone; } }
package OneToManyDouble; public class Linkman { private Integer link_id; private String link_name; private String link_sex; private Customer customer; public Customer getCustomer() { return customer; } public void setCustomer(Customer customer) { this.customer = customer; } public Integer getLink_id() { return link_id; } public void setLink_id(Integer link_id) { this.link_id = link_id; } public String getLink_name() { return link_name; } public void setLink_name(String link_name) { this.link_name = link_name; } public String getLink_sex() { return link_sex; } public void setLink_sex(String link_sex) { this.link_sex = link_sex; } }
<?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"> <!-- javabean与表的映射关系 --> <hibernate-mapping> <class name="OneToManyDouble.Customer" table="customer"> <!-- 主键对应 --> <id name="cus_id"> <generator class="native"></generator> </id> <property name="cus_name" /> <property name="cus_phone"></property> <!-- 设置与多方的关系 --> <set name="linkmans"> <key column="link_cus_id"></key> <one-to-many class="OneToManyDouble.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> <class name="OneToManyDouble.Linkman" table="linkman"> <!-- 主键对应 --> <id name="link_id"> <generator class="native"></generator> </id> <property name="link_name" /> <property name="link_sex"></property> <!-- 建立多方 和 指定外键 --> <many-to-one name="customer" class="OneToManyDouble.Customer" column="link_cus_id" /> </class> </hibernate-mapping>
5单向【N-1】
单向的【N-1】关联只能从【N】的一端访问【1】的一端。
一个买家对应多个订单。
只需要在Order中定义一个Buyer类型的属性,而不需要在Buyer中定义存放Order对象的集合属性。
注意mysql里order属于关键字,最好改名。
package ManyToOneSingle; public class Buyer { private Integer buyerId; private String buyerName; private String password; public Buyer() { } public Integer getBuyerId() { return buyerId; } public void setBuyerId(Integer buyerId) { this.buyerId = buyerId; } public String getBuyerName() { return buyerName; } public void setBuyerName(String buyerName) { this.buyerName = buyerName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
package ManyToOneSingle; public class Order { private Integer orderId; private String orderNo; private Buyer buyer; public Integer getOrderId() { return orderId; } public void setOrderId(Integer orderId) { this.orderId = orderId; } public String getOrderNo() { return orderNo; } public void setOrderNo(String orderNo) { this.orderNo = orderNo; } public Buyer getBuyer() { return buyer; } public void setBuyer(Buyer buyer) { this.buyer = buyer; } }
6单向【N-N】
每个N-N的实质都存在一个中间表。
只有主动方对象关联被动方对象,而被动方对象没有关联主动方对象。
此例子中Form是主动发,product是被动方。
一个Form对象可以包含一个或者多个不同的Product对象,
而同一个Product对象可以被0个或者多个不同的Order对象所包含。
主动方的配置中:
set的table属性指明了两个对象间连接表的表名。
key用于连接表中这只关于form【主动方】的外键和外键名。
manytomany中的column属性用于设置连接表引用自【被动方】product的外键和外键名。
package ManyToManySingle; import java.util.HashSet; import java.util.Set; public class Form { private Integer formId; private String formName; private Set<Product> products = new HashSet<Product>(); public Integer getFormId() { return formId; } public void setFormId(Integer formId) { this.formId = formId; } public String getFormName() { return formName; } public void setFormName(String formName) { this.formName = formName; } public Set<Product> getProducts() { return products; } public void setProducts(Set<Product> products) { this.products = products; } }
package ManyToManySingle; public class Product { private Integer productId; private String productName; public Integer getProductId() { return productId; } public void setProductId(Integer productId) { this.productId = productId; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } }
<?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> <class name="ManyToManySingle.Form" table="form"> <id name="formId"> <generator class="native"></generator> </id> <property name="formName" /> <!-- table表示中间表 --> <set name="products" table="formitem"> <key column="form_id"/> <!-- 设置了连接表中引用Product的外键名为product_id --> <many-to-many class="ManyToManySingle.Product" column="product_id"></many-to-many> </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> <class name="ManyToManySingle.Product" table="product"> <id name="productId"> <generator class="native"></generator> </id> <property name="productName" /> </class> </hibernate-mapping>
7双向【N-N】
主动方和被动方相互关联。两方都有set集合。
要任选一方放弃外键维护防止冲突。
package ManyToManyDouble; import java.util.HashSet; import java.util.Set; public class People { private Integer peopleId; private String peopleName; private Set<Role> roles = new HashSet<Role>();//这里一定要new出来。 public Integer getPeopleId() { return peopleId; } public void setPeopleId(Integer peopleId) { this.peopleId = peopleId; } public String getPeopleName() { return peopleName; } public void setPeopleName(String peopleName) { this.peopleName = peopleName; } public Set<Role> getRoles() { return roles; } public void setRoles(Set<Role> roles) { this.roles = roles; } }
package ManyToManyDouble; import java.util.HashSet; import java.util.Set; public class Role { private Integer roleId; private String roleName; private Set<People> peoples = new HashSet<People>(); public Integer getRoleId() { return roleId; } public void setRoleId(Integer roleId) { this.roleId = roleId; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public Set<People> getPeoples() { return peoples; } public void setPeoples(Set<People> peoples) { this.peoples = peoples; } }
<?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> <class name="ManyToManyDouble.People" table="People"> <id name="peopleId"> <generator class="native"></generator> </id> <property name="peopleName" /> <set name="roles" table="roleitem" inverse="true"> <key column="people_id" /> <many-to-many class="ManyToManyDouble.Role" column="role_id" /> </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> <class name="ManyToManyDouble.Role" table="Role"> <id name="roleId"> <generator class="native"></generator> </id> <property name="roleName" /> <set name="peoples" table="roleitem"> <key column="role_id" /> <many-to-many class="ManyToManyDouble.People" column="people_id" /> </set> </class> </hibernate-mapping>
所有测试用例
package Test; import org.hibernate.Session; import org.hibernate.Transaction; import com.yiki.util.Utils; import OneToOneDouble.Husband; import OneToOneDouble.Wife; public class Double_1_1 { public static void main(String[] args) { Session session = Utils.openSession(); Transaction tr = session.beginTransaction(); Husband husband = new Husband(); Wife wife = new Wife(); husband.setHusbanName("o"); wife.setWifeName("w"); husband.setWife(wife); wife.setHusband(husband); session.save(wife); session.save(husband); tr.commit(); session.close(); } }
package Test; import org.hibernate.Session; import org.hibernate.Transaction; import com.yiki.util.Utils; import OneToManyDouble.Customer; import OneToManyDouble.Linkman; public class Double_1_N { public static void main(String[] args) { Session session = Utils.openSession(); Transaction tr = session.beginTransaction(); Customer c1 = new Customer(); Linkman link1 = new Linkman(); link1.setLink_name("联系人1"); Linkman link2 = new Linkman(); link2.setLink_name("联系人2"); c1.setCus_name("cus1"); c1.setCus_phone("3333333"); //双向关联 c1.getLinkmans().add(link1); c1.getLinkmans().add(link2); link1.setCustomer(c1); link2.setCustomer(c1); session.save(c1); session.save(link1); session.save(link2); tr.commit(); session.close(); } }
package Test; import org.hibernate.Session; import org.hibernate.Transaction; import com.yiki.util.Utils; import ManyToManyDouble.People; import ManyToManyDouble.Role; public class Double_N_N { public static void main(String[] args) { Session session = Utils.openSession(); Transaction tr = session.beginTransaction(); People p1 = new People(); p1.setPeopleName("tiffany"); People p2 = new People(); p2.setPeopleName("yiki"); People p3 = new People(); p3.setPeopleName("penny"); Role r1 = new Role(); r1.setRoleName("engineer"); Role r2 = new Role(); r2.setRoleName("girl"); Role r3 = new Role(); r3.setRoleName("singer"); p1.getRoles().add(r2); r2.getPeoples().add(p1); r2.getPeoples().add(p1); p2.getRoles().add(r3); r3.getPeoples().add(p2); p3.getRoles().add(r2); r2.getPeoples().add(p3); session.save(p1); session.save(p2); session.save(p3); session.save(r1); session.save(r2); session.save(r3); tr.commit(); session.close(); } }
package Test; import org.hibernate.Session; import org.hibernate.Transaction; import com.yiki.util.Utils; import OneToOneSingle.User; import OneToOneSingle.UserInfo; public class single_1_1 { public static void main(String[] args) { Session session = Utils.openSession(); Transaction tr = session.beginTransaction(); User user = new User(); UserInfo info = new UserInfo(); info.setAddress("Chongqin"); info.setMail("[email protected]"); user.setUsername("tiffany"); user.setPassword("22222"); user.setUserinfo(info); session.save(user); session.save(info); tr.commit(); session.close(); } }
package Test; import org.hibernate.Session; import org.hibernate.Transaction; import com.yiki.util.Utils; import OneToManySingle.Student; import OneToManySingle.Teacher; public class Single_1_N { public static void main(String[] args) { Session session = Utils.openSession(); Transaction tr = session.beginTransaction(); Teacher teacher = new Teacher(); Student s1 = new Student(); Student s2 = new Student(); teacher.setTeacherName("老师1"); teacher.setTeacherAge(34); s1.setStudentName("yi"); s1.setStudentSex("male"); s2.setStudentName("ki"); s2.setStudentSex("female"); teacher.getStudents().add(s1); teacher.getStudents().add(s2); session.save(s1); session.save(s2); session.save(teacher); tr.commit(); session.close(); } }
package Test; import org.hibernate.Session; import org.hibernate.Transaction; import com.yiki.util.Utils; import ManyToOneSingle.Buyer; import ManyToOneSingle.Order; public class Single_N_1 { public static void main(String[] args) { addBuyerAndOrder(); } public static void addBuyerAndOrder(){ Buyer buyer = new Buyer(); buyer.setBuyerName("tiffany"); buyer.setPassword("123344"); addBuyer(buyer); Order order = new Order(); order.setBuyer(buyer); order.setOrderNo("2"); addOrder(order); } private static void addOrder(Order order) { Session session = Utils.openSession(); Transaction tr = session.beginTransaction(); session.save(order); tr.commit(); session.close(); } private static void addBuyer(Buyer buyer) { Session session = Utils.openSession(); Transaction tr = session.beginTransaction(); session.save(buyer); tr.commit(); session.close(); } }
package Test; import org.hibernate.Session; import org.hibernate.Transaction; import com.yiki.util.Utils; import ManyToManySingle.Form; import ManyToManySingle.Product; public class Single_N_N { public static void main(String[] args) { Session session = Utils.openSession(); Transaction tr = session.beginTransaction(); Product p1 = new Product(); Product p2 = new Product(); Form f1 = new Form(); Form f2 = new Form(); p1.setProductName("产品1"); p2.setProductName("产品2"); f1.setFormName("订单1"); f2.setFormName("订单2"); f1.getProducts().add(p1); f1.getProducts().add(p2); f2.getProducts().add(p1); session.save(p1); session.save(p2); session.save(f1); session.save(f2); tr.commit(); session.close(); } }
会话池
package com.yiki.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /* * 工具包*/ @SuppressWarnings("deprecation") public class Utils { public static final Configuration CFG; public static final SessionFactory FACTORY; // Configuration config = new Configuration(); // config.configure(); // serviceRegistry = new // ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry(); // sessionFactory = config.buildSessionFactory(serviceRegistry); // Session session = sessionFactory.getCurrentSession(); static { CFG = new Configuration().configure(); FACTORY = CFG.buildSessionFactory(); } public static Session openSession() { return FACTORY.openSession(); } }