05.Hibernate多对多关联

时间:2021-08-14 16:17:02
    前言:本文讲解使用Hibernate映射多对多关联关系,并使用多种方式映射多对多关联。

1.数据库表的多对多关系

    本文根据学生信息表(tb_student)和教师信息表(tb_teacher)来说明多对多映射关系,一个学生有多个老师,一个老师也有多个学生,其数据库模型图如下:
        05.Hibernate多对多关联
    根据以上图,对应的建表语句如下:
  1. CREATE TABLE tb_student
  2. (
  3. id bigint NOT NULL auto_increment COMMENT 'ID',
  4. no varchar(10) NOT NULL COMMENT '学号',
  5. name varchar(50) NOT NULL COMMENT '姓名',
  6. sex char(1) NOT NULL COMMENT '性别',
  7. birthday datetime COMMENT '出生日期',
  8. class_id bigint COMMENT '班级ID',
  9. PRIMARY KEY (id)
  10. ) COMMENT = '学生信息表';
  11. CREATE TABLE tb_teacher
  12. (
  13. id bigint NOT NULL auto_increment COMMENT 'ID',
  14. no varchar(10) NOT NULL COMMENT '教师编号',
  15. name varchar(50) NOT NULL COMMENT '教师姓名',
  16. sex char(1) NOT NULL COMMENT '教师性别',
  17. job_title varchar(50) NOT NULL COMMENT '职称',
  18. PRIMARY KEY (id)
  19. ) COMMENT = '教师信息表';
  20. CREATE TABLE tb_student_teacher
  21. (
  22. student_id bigint NOT NULL COMMENT '学生ID',
  23. teacher_id bigint NOT NULL COMMENT '教师ID',
  24. PRIMARY KEY (student_id,teacher_id)
  25. ) COMMENT = '学生教师关系表';
  26. -- 可选的外键约束
  27. ALTER TABLE tb_student_teacher ADD CONSTRAINT fk_student_id FOREIGN KEY (student_id) REFERENCES tb_student (id);
  28. ALTER TABLE tb_student_teacher ADD CONSTRAINT fk_teacher_id FOREIGN KEY (teacher_id) REFERENCES tb_teacher (id);
    编写对应的实体类代码如下:
  1. package model;
  2. import java.sql.Date;
  3. import java.util.HashSet;
  4. import java.util.Set;
  5. public class Student
  6. {
  7. private Long id;
  8. private String no;
  9. private String name;
  10. private String sex;
  11. private Date birthday;
  12. private Long classId;
  13. private Set<Teacher> teachers=new HashSet<Teacher>();
  14. @Override
  15. public String toString()
  16. {
  17. return "Student [id=" + id + ", no=" + no + ", name=" + name + ", sex=" + sex + ", birthday=" + birthday + ", classId=" + classId + ", teachers=" + teachers.size() + "]";
  18. }
  19. //省略setter、getter...
  20. }
  1. package model;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. public class Teacher
  5. {
  6. private Long id;
  7. private String no;
  8. private String name;
  9. private String sex;
  10. private String job_title;
  11. private Set<Student> students=new HashSet<Student>();
  12. @Override
  13. public String toString()
  14. {
  15. return "Teacher [id=" + id + ", no=" + no + ", name=" + name + ", sex=" + sex + ", job_title=" + job_title + ", students=" + students.size() + "]";
  16. }
  17. //省略setter、getter...
  18. }

2.单向多对多关系

    多对多关系也有单向多对多和双向多对多,下面这个例子讲解从Teacher类到Student类的单向多对多关系,配置如下:
  1. <hibernate-mapping package="model">
  2. <class name="Student" table="tb_student">
  3. <id name="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="no" column="no"/>
  7. <property name="name" column="name"/>
  8. <property name="sex" column="sex"/>
  9. <property name="birthday" column="birthday"/>
  10. <property name="classId" column="class_id"/>
  11. </class>
  12. </hibernate-mapping>
  1. <hibernate-mapping package="model">
  2. <class name="Teacher" table="tb_teacher">
  3. <id name="id" column="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="no" column="no" />
  7. <property name="name" column="name" />
  8. <property name="sex" column="sex" />
  9. <property name="job_title" column="job_title" />
  10. <set name="students" table="tb_student_teacher" cascade="save-update">
  11. <key column="teacher_id"/>
  12. <many-to-many class="model.Student" column="student_id" />
  13. </set>
  14. </class>
  15. </hibernate-mapping>
    对于以上配置要注意一下几点:
    1. 由于实体类使用的是Set集合所以使用set元素配置关联关系,根据实体类的集合类型也可以对应的使用idbag、list、map元素。
    2. 由于tb_student表与tb_teacher表的多对多关系是通过tb_student_teacher表来保存的,所以set元素的table属性设置成table="tb_student_teacher"。
    3. set元素的key子元素设置column="teacher_id",表示tb_student_teacher表中参照tb_teacher表的外键设置为teacher_id。
    4. set元素的many-to-many子元素设置class="model.Student",表示Teacher类的students属性的类型,而其column="student_id",表示tb_student_teacher表中参照model.Student类型对应的表的外键设置为student_id。
    5. 所以set元素的cascade属性设置成save-update是很合理的,不允许把cascade设置成all、delete、all-delete-orphands,假如删除一个Teacher对象时还会级联删除与他关联的所有Student对象,由于Student对象可能还会与其他的Teacher对象关联,因此当Hibernate执行级联删除时会违反数据库的外键参照完整性!
    测试程序如下:
  1. public static void main(String[] args)
  2. {
  3. Teacher teacher;
  4. Configuration cfg = new Configuration();
  5. cfg.configure();
  6. ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
  7. SessionFactory sf = cfg.buildSessionFactory(sr);
  8. System.out.println("连接数据库");
  9. Session session = sf.openSession();

  10. teacher =(Teacher) session.get(Teacher.class, new Long(1));
  11. System.out.println(teacher);
  12. System.out.println(teacher.getStudents());

  13. session.close();
  14. System.exit(0);
  15. }
    控制台输出如下:
  1. 连接数据库
  2. Hibernate:
  3. select
  4. teacher0_.id as id1_7_0_,
  5. teacher0_.no as no2_7_0_,
  6. teacher0_.name as name3_7_0_,
  7. teacher0_.sex as sex4_7_0_,
  8. teacher0_.job_title as job_titl5_7_0_
  9. from
  10. tb_teacher teacher0_
  11. where
  12. teacher0_.id=?
  13. Hibernate:
  14. select
  15. students0_.teacher_id as teacher_1_7_0_,
  16. students0_.student_id as student_2_6_0_,
  17. student1_.id as id1_5_1_,
  18. student1_.no as no2_5_1_,
  19. student1_.name as name3_5_1_,
  20. student1_.sex as sex4_5_1_,
  21. student1_.birthday as birthday5_5_1_,
  22. student1_.class_id as class_id6_5_1_
  23. from
  24. tb_student_teacher students0_
  25. inner join
  26. tb_student student1_
  27. on students0_.student_id=student1_.id
  28. where
  29. students0_.teacher_id=?
  30. Teacher [id=1, no=000001, name=教师1, sex=女, job_title=初级教师, students=1]
  31. Hibernate:
  32. select
  33. teachers0_.student_id as student_2_5_0_,
  34. teachers0_.teacher_id as teacher_1_6_0_,
  35. teacher1_.id as id1_7_1_,
  36. teacher1_.no as no2_7_1_,
  37. teacher1_.name as name3_7_1_,
  38. teacher1_.sex as sex4_7_1_,
  39. teacher1_.job_title as job_titl5_7_1_
  40. from
  41. tb_student_teacher teachers0_
  42. inner join
  43. tb_teacher teacher1_
  44. on teachers0_.teacher_id=teacher1_.id
  45. where
  46. teachers0_.student_id=?
  47. [Student [id=1, no=000001, name=学生1, sex=男, birthday=2015-01-27, classId=41, teachers=1]]
  48. 关闭数据库
    根据输出可以看出Hibernate会根据inner join连接查询获取关联数据。

3.双向多对多关系

    使用双向关联与单向关联类似,只是在Student类与Teacher类两方都配置了set元素进行关联,配置如下:
  1. <hibernate-mapping package="model">
  2. <class name="Student" table="tb_student">
  3. <id name="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="no" column="no"/>
  7. <property name="name" column="name"/>
  8. <property name="sex" column="sex"/>
  9. <property name="birthday" column="birthday"/>
  10. <property name="classId" column="class_id"/>
  11. <set name="teachers" table="tb_student_teacher" cascade="save-update" inverse="true">
  12. <key column="student_id"/>
  13. <many-to-many class="model.Teacher" column="teacher_id"/>
  14. </set>
  15. </class>
  16. </hibernate-mapping>
  1. <hibernate-mapping package="model">
  2. <class name="Teacher" table="tb_teacher">
  3. <id name="id" column="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="no" column="no" />
  7. <property name="name" column="name" />
  8. <property name="sex" column="sex" />
  9. <property name="job_title" column="job_title" />
  10. <set name="students" table="tb_student_teacher" cascade="save-update" inverse="false">
  11. <key column="teacher_id"/>
  12. <many-to-many class="model.Student" column="student_id" />
  13. </set>
  14. </class>
  15. </hibernate-mapping>
    注意:对于双向多对多关联的两端,必须把其中一端的<set>元素的inverse属性设置成true,同时建立关联时必须同时建立从Teacher类到Student类,以及从Student类到Teacher类的关联关系!
    以上的关联两端都使用<set>元素,但是在双向多对多关联中值得注意的是:必须把其中的一端的inverse属性设置成true,另一端设置成false。并且在inverse="false"的一端可以使用set、idbag、list、map元素,而在inverse="true"的一端只能使用set元素和bag元素!由于Student是inverse="true"的一端,Hibernate不会根据teachers对象的集合的变化同步更新tb_student_teacher连接表,因此无法通过该连接表来保存Student对象的teachers集合中各个Teacher对象的索引位置。

4.使用组件类集合映射多对多关联

    在上面的例子中Student类中有一个teachers集合属性,同样在Teacher类中有一个students集合属性,关联关系由Student类和Teacher类来维护。除了这种方式以外Hibernate还支持使用组件类的集合属性来维护关联关系,下面使用组件类集合映射多对多关系,数据库表结构不变,对实体类修改如下图:
    05.Hibernate多对多关联
    对应的代码如下:
  1. package model;
  2. import java.sql.Date;
  3. import java.util.HashSet;
  4. import java.util.Set;
  5. public class Student
  6. {
  7. private Long id;
  8. private String no;
  9. private String name;
  10. private String sex;
  11. private Date birthday;
  12. private Long classId;
  13. private Set<TeacherAndStudent> teacherAndStudents = new HashSet<TeacherAndStudent>();
  14. @Override
  15. public String toString()
  16. {
  17. return "Student [id=" + id + ", no=" + no + ", name=" + name + ", sex=" + sex + ", birthday=" + birthday + ", classId=" + classId + "]";
  18. }
  19. // 省略setter、getter...
  20. }
  1. package model;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. public class Teacher
  5. {
  6. private Long id;
  7. private String no;
  8. private String name;
  9. private String sex;
  10. private String job_title;
  11. private Set<TeacherAndStudent> teacherAndStudents = new HashSet<TeacherAndStudent>();
  12. @Override
  13. public String toString()
  14. {
  15. return "Teacher [id=" + id + ", no=" + no + ", name=" + name + ", sex=" + sex + ", job_title=" + job_title + "]";
  16. }
  17. // 省略setter、getter...
  18. }
  1. package model;
  2. public class TeacherAndStudent
  3. {
  4. private Teacher teacher;
  5. private Student student;
  6. @Override
  7. public String toString()
  8. {
  9. return "TeacherAndStudent [teacher=" + teacher + ", student=" + student + "]";
  10. }
  11. // 省略setter、getter...
  12. }
    其中组件类是TeacherAndStudent,相对于实体类他有一个特点就是没有OID!对应的配置映射文件如下:
  1. <hibernate-mapping package="model">
  2. <class name="Student" table="tb_student">
  3. <id name="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="no" column="no"/>
  7. <property name="name" column="name"/>
  8. <property name="sex" column="sex"/>
  9. <property name="birthday" column="birthday"/>
  10. <property name="classId" column="class_id"/>
  11. <set name="teacherAndStudents" table="tb_student_teacher" cascade="save-update" inverse="true">
  12. <key column="student_id" />
  13. <composite-element class="TeacherAndStudent">
  14. <parent name="student" />
  15. <many-to-one name="teacher" class="Teacher" column="teacher_id"/>
  16. </composite-element>
  17. </set>
  18. </class>
  19. </hibernate-mapping>
  1. <hibernate-mapping package="model">
  2. <class name="Teacher" table="tb_teacher">
  3. <id name="id" column="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="no" column="no" />
  7. <property name="name" column="name" />
  8. <property name="sex" column="sex" />
  9. <property name="job_title" column="job_title" />
  10. <set name="teacherAndStudents" table="tb_student_teacher" cascade="save-update" inverse="false">
  11. <key column="teacher_id"/>
  12. <composite-element class="TeacherAndStudent">
  13. <parent name="teacher"/>
  14. <many-to-one name="student" class="Student" column="student_id"/>
  15. </composite-element>
  16. </set>
  17. </class>
  18. </hibernate-mapping>
    对于以上的配置的说明如下:
    1. 在Hibernate中使用composite-element元素映射组件类。
    2. composite-element元素下的parent元素用来设置当前组件所属的整体类。
    3. composite-element元素下还可以使用many-to-one元素和property元素等。
    关于组件映射的内容细节将会在后面的文章中讲到,在这里就不做深入的讲解了,测试代码如下:
  1. public static void main(String[] args)
  2. {
  3. Teacher teacher;
  4. Configuration cfg = new Configuration();
  5. cfg.configure();
  6. ServiceRegistry sr = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
  7. SessionFactory sf = cfg.buildSessionFactory(sr);
  8. System.out.println("连接数据库");
  9. Session session = sf.openSession();
  10. teacher =(Teacher) session.get(Teacher.class, new Long(1));
  11. System.out.println(teacher);
  12. System.out.println(teacher.getTeacherAndStudents());
  13. session.close();
  14. System.exit(0);
  15. }
    值得注意的是:由于TeacherAndStudent类是一个组件类(没有OID),所以不能调用Session的保存、更新、删除等方法对他进行操作!
    一下是程序运行的结果:
  1. 连接数据库
  2. Hibernate:
  3. select
  4. teacher0_.id as id1_7_0_,
  5. teacher0_.no as no2_7_0_,
  6. teacher0_.name as name3_7_0_,
  7. teacher0_.sex as sex4_7_0_,
  8. teacher0_.job_title as job_titl5_7_0_
  9. from
  10. tb_teacher teacher0_
  11. where
  12. teacher0_.id=?
  13. Teacher [id=1, no=000001, name=教师1, sex=女, job_title=初级教师]
  14. Hibernate:
  15. select
  16. teacherand0_.teacher_id as teacher_1_7_0_,
  17. teacherand0_.student_id as student_2_6_0_,
  18. student1_.id as id1_5_1_,
  19. student1_.no as no2_5_1_,
  20. student1_.name as name3_5_1_,
  21. student1_.sex as sex4_5_1_,
  22. student1_.birthday as birthday5_5_1_,
  23. student1_.class_id as class_id6_5_1_
  24. from
  25. tb_student_teacher teacherand0_
  26. left outer join
  27. tb_student student1_
  28. on teacherand0_.student_id=student1_.id
  29. where
  30. teacherand0_.teacher_id=?
  31. [TeacherAndStudent [teacher=Teacher [id=1, no=000001, name=教师1, sex=女, job_title=初级教师], student=Student [id=1, no=000001, name=学生1, sex=男, birthday=2015-01-27, classId=41]]]
  32. Hibernate:
  33. delete
  34. from
  35. tb_student_teacher
  36. where
  37. teacher_id=?
  38. Hibernate:
  39. insert
  40. into
  41. tb_student_teacher
  42. (teacher_id, student_id)
  43. values
  44. (?, ?)
  45. 关闭数据库

5.把多对多分解成两个一对多

    事实上,所有的多对多关联都可以分解成两个一对多关联,按照这种方式映射多对多关联,会使域模型和关系数据库模型会有更好的扩展性。下面我再以上的基础上再新建一张表(tb_teacher_student),和一个实体类(StudentTeacher),并对以前的实体类做细微的修改,具体如下。
    新建tb_teacher_student表的语句:
  1. CREATE TABLE tb_teacher_student
  2. (
  3. id bigint NOT NULL auto_increment COMMENT 'ID',
  4. student_id bigint COMMENT '学生ID',
  5. teacher_id bigint COMMENT '教师ID',
  6. PRIMARY KEY (id)
  7. ) COMMENT = '教师学生关系表';
    新建的实体类StudentTeacher:
  1. package model;
  2. public class StudentTeacher
  3. {
  4. private Long id;
  5. private Teacher teacher;
  6. private Student student;
  7. @Override
  8. public String toString()
  9. {
  10. return "StudentTeacher [id=" + id + ", teacher=" + teacher + ", student=" + student + "]";
  11. }
  12. // 省略setter、getter...
  13. }
    修改后的实体类:
  1. package model;
  2. import java.sql.Date;
  3. import java.util.HashSet;
  4. import java.util.Set;
  5. public class Student
  6. {
  7. private Long id;
  8. private String no;
  9. private String name;
  10. private String sex;
  11. private Date birthday;
  12. private Long classId;
  13. private Set<StudentTeacher> studentTeachers = new HashSet<StudentTeacher>();
  14. @Override
  15. public String toString()
  16. {
  17. return "Student [id=" + id + ", no=" + no + ", name=" + name + ", sex=" + sex + ", birthday=" + birthday + ", classId=" + classId + "]";
  18. }
  19. // 省略setter、getter...
  20. }
  1. package model;
  2. import java.util.HashSet;
  3. import java.util.Set;
  4. public class Teacher
  5. {
  6. private Long id;
  7. private String no;
  8. private String name;
  9. private String sex;
  10. private String job_title;
  11. private Set<StudentTeacher> studentTeachers = new HashSet<StudentTeacher>();
  12. @Override
  13. public String toString()
  14. {
  15. return "Teacher [id=" + id + ", no=" + no + ", name=" + name + ", sex=" + sex + ", job_title=" + job_title + "]";
  16. }
  17. // 省略setter、getter...
  18. }
    对应的配置文件如下,只是用了一对多的双向关联,这里给出代码就不多讲了:
  1. <hibernate-mapping package="model">
  2. <class name="StudentTeacher" table="tb_teacher_student">
  3. <id name="id" column="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <many-to-one name="teacher" column="teacher_id" class="Teacher"/>
  7. <many-to-one name="student" column="student_id" class="Student"/>
  8. </class>
  9. </hibernate-mapping>
  1. <hibernate-mapping package="model">
  2. <class name="Teacher" table="tb_teacher">
  3. <id name="id" column="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="no" column="no" />
  7. <property name="name" column="name" />
  8. <property name="sex" column="sex" />
  9. <property name="job_title" column="job_title" />
  10. <set name="studentTeachers" inverse="true" cascade="save-update">
  11. <key column="teacher_id" />
  12. <one-to-many class="StudentTeacher"/>
  13. </set>
  14. </class>
  15. </hibernate-mapping>
  1. <hibernate-mapping package="model">
  2. <class name="Student" table="tb_student">
  3. <id name="id">
  4. <generator class="native"></generator>
  5. </id>
  6. <property name="no" column="no"/>
  7. <property name="name" column="name"/>
  8. <property name="sex" column="sex"/>
  9. <property name="birthday" column="birthday"/>
  10. <property name="classId" column="class_id"/>
  11. <set name="studentTeachers" inverse="true" cascade="save-update">
  12. <key column="student_id" />
  13. <one-to-many class="StudentTeacher"/>
  14. </set>
  15. </class>
  16. </hibernate-mapping>
    测试代码,以及运行结果如下:
  1. ......省略打开session的代码
  2. try
  3. {
  4. teacher =(Teacher) session.get(Teacher.class, new Long(1));
  5. student = (Student) session.get(Student.class, new Long(1));
  6. StudentTeacher st=new StudentTeacher();
  7. st.setStudent(student);
  8. st.setTeacher(teacher);
  9. student.getStudentTeachers().add(st);
  10. session.update(student);
  11. transaction.commit();
  12. }
  13. ......省略关闭session的代码
  1. 连接数据库
  2. Hibernate: ........ 省略若干获取关联对象的查询语句
  3. Hibernate: insert into tb_teacher_student (teacher_id, student_id) values (?, ?)
  4. 关闭数据库
    事实上,所有的多对多关联都可以分解成两个一对多关联,按照这种方式映射多对多关联,会使域模型和关系数据库模型会有更好的扩展性。

6.相关配置详解

(1)set节点配置说明
  1. <set name="EntityClassName"
  2. access="field|property|ClassName"
  3. collection-type="collection-type"
  4. schema="schema"
  5. catalog="catalog"
  6. check="arbitrary sql check condition"
  7. table="TableName"
  8. subselect="SQL expression"
  9. where="arbitrary sql where condition"
  10. sort="unsorted"
  11. optimistic-lock="false|true"
  12. inverse="false|true"
  13. fetch="join|select"
  14. batch-size="5"
  15. cascade="all|none|save-update|delete"
  16. lazy="false|true"
  17. mutable="false|true"
  18. outer-join="false|true"
  19. order-by="arbitrary sql order by condition"
  20. embed-xml="false|true"
  21. persister="PersisterClass"
  22. node="element-name"/>
    如上展示了set节点常用的配置,与bag节点基本一样只是多了sort属性是面对其配置进行详细的说明:
  1. name:实体类属性名。
  2. access:默认的实体类属性访问模式,取值为property表示访问getter、setter方法间接访问实体类字段,取值为field表示直接访问实体类字段(类成员变量)。
  3. collection-type:
  4. schema:数据库schema。
  5. catalog:数据库catalog。
  6. check:这是一个SQL表达式,用于为自动生成的schema添加多行约束检查。
  7. table:此集合里的实体类对应的数据库表名。
  8. subselect:一个SQL子查询,它将一个不可变并且只读的实体映射到一个数据库的子查询。
  9. where:一个SQL查询的where条件,获取这个关联类的对象时会一直增加这个条件。
  10. sort:用来定义集合的排序规则,sort="natural"表示使用对象的comparaTo()方法排序。
  11. optimistic-lock:指定这个属性在做更新时是否需要获得乐观锁定,默认为true。
  12. inverse:当设置inverse="true"时,Hibernate将根此集合里的实体类类型的关联属性维护关联关系,默认值false。
  13. fetch:参数指定了关联对象抓取的方式是select查询还是join查询,默认为select。fetch="join"等同于outer-join="true",fetch="select"等同于outer-join="false"。
  14. batch-size:用于设置批次操作的SQL语句的数量,默认为1。
  15. cascade:指明哪些操作会从父对象级联到关联的对象。
  16. lazy:是否采用延迟加载策略。
  17. mutable:此集合里的实体类是否会发生改变,如果类实例对应的数据库表记录不会发生更新,可将其设为false,适用于单纯的Insert操作不使用update操作。
  18. outer-join:设置Hibernate是否使用外连接获取关联的数据,设置成true可以减少SQL语句的条数。
  19. order-by:一个SQL查询的order by条件,获取这个关联类的对象时会一直增加这个条件。
  20. embed-xml:如果embed-xml="true",则对应于被关联实体或值类型的集合的XML树将直接嵌入拥有这些关联的实体的XML树中,默认值为true。
  21. persister:指定持久化实现类,通过指定持久化类,我们可以实现自定义的持久化方法。持久化类为ClassPersister接口的实现。
  22. node:配置说明。
(2)composite-element节点配置说明
  1. <composite-element class="ClassName" node="element-name">
  2. <parent name="PropertyName" />
  3. <property name="PropertyName"></property>
  4. <many-to-one />
  5. </composite-element>
  1. class:用于设置组件的类型。
  2. node:配置说明。
  3. parent name:组件所属的实体类类型,值一般是组件类本身的实体类属性。
  4. property:组件类属性名。
  5. many-to-one:用于配置组件类的关联关系,不仅能使用many-to-one元素,还可使用其他的关联映射配置。

-------------------------------------------------------------------------------------------------------------------------------