之前的博客已经提到一些关于hibernate的基础配置,现在讲些关于hibernate的关联配置
1:多对一的关系
public class Books implements Serializable {
private String author;
private Publishers publishers;
get和set方法
}
<hibernate-mapping>
<class name="com.model.Books" table="books">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="assigned" />
</id>
.....中间省略........
<many-to-one name="publishers" column="PublisherId"
class="com.model.Publishers" insert="true" update="true"
lazy="false" />
......中间省略.......
</class>
</hibernate-mapping>
注:<many-to-one>有如下要求:
name:表示实体属性的名字
column:实体关联字段
class:实体属性类型
测试程序:
public class TestOneToMany extends BaseHibernateDao {
public static void main(String[] args) {
// TODO Auto-generated method stub
TestOneToMany test = new TestOneToMany();
test.TestOneToMany();
}
public void TestOneToMany(){
Publishers publishers = (Publishers)super.get(Publishers.class, new Integer(1));
System.out.println(publishers.getName());
Iterator iter = publishers.getBks().iterator();
while (iter.hasNext()) {
Books books = (Books) iter.next();
System.out.println(books.getTitle());
}
}
}
//由于是一对多的关系,所以要用一个iterator进行迭代输出。
Iterator iter = publishers.getBks().iterator();
while(iter.hasNext()){
//转换成Books类型
Books books = (Books)iter.next();
} 这几句话是重点
public abstract class BaseHibernateDao {
public Object get(Class cla , Serializable id){
Object object = null;
Configuration conf = new Configuration().configure();
SessionFactory sessionFactory = conf.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tc =null;
try {
object = session.get(cla, id);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally{
session.close();
}
return object;
}
}
2一对多的关系:一个实体对象有多个集合属性,建议采用set的方式进行存储。
public class Publishers implements Serializable {
private Integer id;
private String name;
//因为publishers 与Books 是一对多的关系,所以需要一个集合类型的属性来关联到Books类
private Set bks = new HashSet();
}
<hibernate-mapping>
<class name="com.model.Publishers" table="publishers">
<id name="id" type="java.lang.Integer">
<column name="id"></column>
<generator class="assigned"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<set name="bks" cascade="all" lazy="false" >
<key column="PublisherId" />
<one-to-many class="com.model.Books"/>
</set>
</class>
</hibernate-mapping>
注:cascade="all"表示双向关联,即两个实体可以从一端访问另一端
lazy="false"表示延迟加载,hibernate默认为false,即一张表关联另一张表,不会同时加载它
在多对一的情况下,只需定义对象本身即可。而在一对多的情况下,则需要定义一个set对象来进行加载。
常见错误:
找不到代理类 classcastException,查看数据库表的结构,外键是否多加?列是否准确?数据类是否一致?
org.hibernate.property not found exception 配置文件中,property里的name名字是否写错了。
测试程序:
public class TestManyToOne extends BaseHibernateDao{
public static void main(String[] args) {
// TODO Auto-generated method stub
TestManyToOne test = new TestManyToOne();
test.testManyToOne();
}
public void testManyToOne(){
Books books = (Books)super.get(Books.class, new Integer(1));
System.out.println(books.getAuthor());
}
}
3一对一的关系
一对一的关系,可以通过外键生成,假设有2个类,Card和Person类,Card有int id String cardNo Person person 三个属性,Person有int id ,String name, Card card三个属性。 person.hbm.xml如下:
<id name="id" type="java.lang.Long">
<column name="id"></column>
<generator class="increment"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name"></column>
</property>
<one-to-one name="card" class="com.model.Card" cascade="all"></one-to-one>
card.hbm.xml如下:
<id name="id" type="java.lang.Long"><
<column name="id"></column>
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="cardNo" type="java.lang.String">
<column name="cardNo"></column>
</property>
<!--站在从对象的一方来设置交出约束 -->
<!-- name:一对一节点 ,constrained: 约束(必须为true) -->
<one-to-one name="person" class="com.model.Person" constrained="true"></one-to-one>
注意:这里constrained="true" 和class="foreign"只需设置一次
.测试程序如下:
public class TestOneToOne extends BaseHibernateDao {
public static void main(String[] args) {
// TODO Auto-generated method stub
TestOneToOne test = new TestOneToOne();
test.TestOneToOne();
}
public void TestOneToOne(){
Person p = new Person();
p.setName("hanxin");
Card c = new Card();
c.setCardNo("122314");
p.setCard(c);
c.setPerson(p);
super.add(p);
super.add(c);
}
}
注意:这里p和c必须要互相关联,否则无法实现。
4多对多关系
多对多实质上就是两个一对多,一般用一个中间表进行拆分,同时确立两个主键。一般的话<key>是用来获得中间值得数据,比如student表和course表,本是多对多关系,中间存放了sc表(sid,cid)。假如是在students.hbm.xml配置,则set里面的key则记录sid的信息,另一个字段信息cid则由many-to-many实现。具体如下:
student.hbm.xml
<class name="com.model.Student" table="student" >
<id name="studentId" type="java.lang.Integer">
<column name="studentId"/>
<generator class="native"></generator>
</id>
<property name="studentName" type="java.lang.String">
<column name="studentName" ></column>
</property>
<set name="courses" table="sc" cascade="all">
<key column="Sid" ></key>
<many-to-many column="Cid" class="com.model.Course" ></many-to-many>
</set>
course.hmb.xml
<class name="com.model.Course" table="course">
<id name="courseId" type="java.lang.Integer">
<column name="CourseId" />
<generator class="native" />
</id>
<property name="courseName" type="java.lang.String">
<column name="CourseName" />
</property>
<set name="students" table="sc" inverse="true" lazy="false">
<key>
<column name="Cid" />
</key>
<many-to-many column="Sid" class="com.model.Student" ></many-to-many>
</set>
</class>
测试程序如下:
public void testAdd_1(){
Student s1 =new Student();
s1.setStudentName("韦小宝");
Student s2 = new Student();
s2.setStudentName("令狐冲");
Course c1 = new Course();
c1.setCourseName("数据结构");
Course c2 = new Course();
c2.setCourseName("操作系统");
Course c3 = new Course();
c3.setCourseName("计算机组成原理");
Course c4 = new Course();
c4.setCourseName("离散数学");
//设定s1与c1 c2互相关联
s1.getCourses().add(c1);
s1.getCourses().add(c2);
c1.getStudents().add(s1);
c2.getStudents().add(s1);
//设定c2与c1 c2 c4互相关联
s2.getCourses().add(c1);
s2.getCourses().add(c3);
s2.getCourses().add(c4);
c1.getStudents().add(s2);
c3.getStudents().add(s2);
c4.getStudents().add(s2);
super.add(s1);
super.add(s2);
super.add(c1);
super.add(c2);
super.add(c3);
super.add(c4);
}