单向一对多关联
一:group Set存储contactPerson对象
多:contactPerson
在一的一方维护关联关系
一端持有多方的引用,为一个集合,Set集合比较常用
单向一对多关联---lazy延迟策略
set集合上可以定义的lazy属性:
-true 默认
-false
-extra --> 除非访问到对象属性,否则不会发出查询对象的具体属性的语句!
比如,求集合的size(),发出的查询语句时select count(*) 效率高!
比如,判断集合是否为空,isEmpty(),也不会发出查询属性的select语句!
extra还能改变集合的语义!
比如Set集合中,判断是否包含需要使用到对象equals() hashcode()
而使用lazy=extra时,会屏蔽掉JDK语法规定(hibernate使用了一个代理对象)
原因在于:lazy=extra时,发出的查询语句"不同"!
Hibernate: select 1 from t_person where gid =? and id =?
hibernate会根据已有条件,选择一个最高效率能得到结果的查询语句进行执行!
一对多单向关联,在一端维护关系,如HashSet集合,最好重写hashcode()和equals()
在对HashSet集合进行判断时,如contains(),remove()方法的调用,底层都会通过Hashcode()和equals()去判断对象是否相等。如果不重写,在集合中管理对象时时,会引发许多问题。如果不了解底层原因,很难解决。
1.如果id生成策略是hilo或者uuid,在内存中直接生成id值的,则可以只根据id值重写hashcode和equals
2.如果id生成策略是native,依赖数据库生成id值的,则不能使用id值来重写hashcode和equals
例如,在级联保存瞬时对象时,这些瞬时对象都没有id值,在往HashSet集合中添加的时候,根据这两个方法,判断出这些对象都是同一个,导致最后只有1个对象被保存。
实体类
package org.leadfar.hibernate.model;
public class ContactPerson {
private int id;
private String name;
public ContactPerson() {
// TODO Auto-generated constructor stub
}
public ContactPerson(String name) {
// TODO Auto-generated constructor stub
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.auction"> <!-- name为实体类 table为映射到数据库中的表 lazy默认为true 延迟发出select语句,直到真正用到对象的属性(非id属性)--> <class name="org.leadfar.hibernate.model.ContactPerson" table="t_person" > <!-- id为数据库标识,作为主键 --> <id name="id"> <generator class="native"/> </id> <property name="name"/> </class> </hibernate-mapping>
package org.leadfar.hibernate.model;
import java.util.HashSet;
import java.util.Set;
public class Group {
private int id;
private String name;
private Set<ContactPerson> persons;//hibernate约定使用集合的接口类型!
//expert 专家模式
public void addPerson(ContactPerson person) {
if(persons == null) {
persons = new HashSet<ContactPerson>();
}
persons.add(person);
}
public Set<ContactPerson> getPersons() {
return persons;
}
public void setPersons(Set<ContactPerson> persons) {
this.persons = persons;
}
public Group() {
// TODO Auto-generated constructor stub
}
public Group(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Grasp 强调类的设计原则
GOF 强制类的职责转移
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.auction"> <!-- name为实体类 table为映射到数据库中的表 lazy默认为true 延迟发出select语句,直到真正用到对象的属性(非id属性)--> <class name="org.leadfar.hibernate.model.Group" table="t_group" > <!-- id为数据库标识,作为主键 --> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="persons"> <!-- 对方表中的记录本方的外键字段名为gid --> <key column="gid"></key> <!-- class说明多的一方:org.leadfar.hibernate.model.ContactPerson --> <one-to-many class="org.leadfar.hibernate.model.ContactPerson"></one-to-many> </set> </class> </hibernate-mapping>
测试
package org.leadfar.hibernate.model;
import java.util.HashSet;
import java.util.Set;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class Test_one2Many_01 extends TestCase {
public void test_save() throws Exception {
Configuration cfg = new Configuration().configure();
SessionFactory sfactory = cfg.buildSessionFactory();
Session session = sfactory.openSession();
try {
session.beginTransaction();
ContactPerson cp1 = new ContactPerson("张三");
session.save(cp1);
ContactPerson cp2 = new ContactPerson("李四");
session.save(cp2);
ContactPerson cp3 = new ContactPerson("王五");
session.save(cp3);
Group g1 = new Group("朋友");
//专家模式(grasp)--对外暴露接口,内部封装具体的方法
g1.addPerson(cp1);//group中有一个集合,存储contactPerson对象
g1.addPerson(cp2);
session.save(g1);
Group g2 = new Group("陌生人");
session.save(g2);
Group g3 = new Group("商务");
g3.addPerson(cp3);
session.save(g3);
//下面的做法不好!
/*Set<ContactPerson> persons1 = new HashSet<ContactPerson>();
persons1.add(cp1);
persons1.add(cp2);
g1.setPersons(persons1);
Set<ContactPerson> persons2 = new HashSet<ContactPerson>();
persons2.add(cp3);
g3.setPersons(persons2);*/
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
session.close();
}
}
//one-to-many 由一找到多--集合--遍历集合-->多
public void test_load() throws Exception {
Configuration cfg = new Configuration().configure();
SessionFactory sfactory = cfg.buildSessionFactory();
Session session = sfactory.openSession();
try {
session.beginTransaction();
Group g = (Group) session.load(Group.class, 1);
g.getId();
g.getName();
Set<ContactPerson> persons = g.getPersons();
for(ContactPerson cp : persons) {
System.out.println(cp.getId());
System.out.println(cp.getName());
}
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
session.close();
}
}
}