映射关系(关联映射,使用xml文件进行配置)
(1)一对一映射(一个公司对应一个地址,地址和公司的关系是一对一)
第一步:建立类
公司类:
//一对一 xml配置
public class CompanyXML {
private int id;
private String name;
private AddressXML addressId;
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;
}
public AddressXML getAddressId() {
return addressId;
}
public void setAddressId(AddressXML addressId) {
this.addressId = addressId;
}
}
地址类:
//一对一 xml配置
public class AddressXML {
private int id;
private String city;
private String country;
private CompanyXML companyXML;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public void setCompanyXML(CompanyXML companyXML) {
this.companyXML = companyXML;
}
public CompanyXML getCompanyXML() {
return companyXML;
}
}
第二步:映射文件
公司类映射文件:(CompanyXML.hbm.xml)
<hibernate-mapping package="hibernate.test.domain">
<class name="CompanyXML" table="companyXML" lazy="true">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<many-to-one name="addressId" class="AddressXML" cascade="all" unique="true">
<column name="address"></column>
</many-to-one>
<!-- <one-to-one name="addressId" class="AddressXML" property-ref="companyXML" cascade="all"></one-to-one> -->
</class>
</hibernate-mapping>
地址类映射文件(AddressXML.hbm.xml):
<hibernate-mapping package="hibernate.test.domain">
<class name="AddressXML" table="addressXML" lazy="true">
<id name="id">
<generator class="native"></generator>
</id>
<property name="city"></property>
<property name="country"></property>
<one-to-one name="companyXML" class="CompanyXML" property-ref="addressId" cascade="all"></one-to-one>
</class>
</hibernate-mapping>
说明: 基于外键的1——1关联,外键可以存放在任意一端,
1、 存放的一端要增加many-to-one元素,并添加unique=”true“,column="映射到本表的字段名"
2、另一端使用one-to-one元素,使用property-ref指定引用关联类的属性;
第三步:配置文件(hibernate.cfg.xml)
添加两个映射:<mapping resource="hibernate/test/xml/AddressXML.hbm.xml"></mapping>
<mapping resource="hibernate/test/xml/CompanyXML.hbm.xml"></mapping>
第四步:测试
public static void main(String[] args) {
// TODO Auto-generated method stub
Session session=null;
Transaction tx=null;
try {
session=HibernateAnnocationUtil.getSession();
tx=session.beginTransaction();
AddressXML addressXML=new AddressXML();
addressXML.setCity("zhengzhou2");
addressXML.setCountry("zhengzhou1");
CompanyXML companyXML=new CompanyXML();
companyXML.setName("yizhilian");
companyXML.setAddressId(addressXML);
session.save(companyXML);
tx.commit();
} catch (Exception e) {
// TODO: handle exception
if(tx!=null)
{
tx.rollback();
}
throw e;
}
finally{
if(session!=null)
{
session.close();
}
}
(2)一对多映射(多对一映射)
第一步:建立类(一个部门中有多个员工,部门与员工之间是一对多的关系)
部门类:
public class Department {
private int deptid;
private String dname;
private String location;
private Set<Employee> employees=new HashSet<Employee>();
public int getDeptid() {
return deptid;
}
public void setDeptid(int deptid) {
this.deptid = deptid;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
}
员工类:
public class Employee {
private int id;
private String name;
private String job;
private Department department;
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;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public void setDepartment(Department department) {
this.department = department;
}
public Department getDepartment() {
return department;
}
}
第二步:映射文件
部门类映射文件(Department.hbm.xml):
<hibernate-mapping package="hibernate.test.domain">
<class name="Department" table="Department" lazy="true">
<id name="deptid">
<generator class="native"></generator>
</id>
<property name="dname" type="java.lang.String"></property>
<property name="location" type="java.lang.String"></property>
<set name="employees" cascade="save-update" inverse="true">
<key>
<column name="department"></column>
</key>
<one-to-many class="Employee"></one-to-many><!-- 表明关系 -->
</set>
</class>
</hibernate-mapping>
员工类映射文件(Employee.hbm.xml):
<hibernate-mapping package="hibernate.test.domain">
<class name="Employee" table="Employee" lazy="true">
<id name="id">
<column name="id"></column>
<generator class="native"></generator>
</id>
<property name="name" type="java.lang.String"></property>
<property name="job" type="java.lang.String"></property>
<many-to-one name="department" class="Department" cascade="save-update" >
<column name="deptid"></column>
</many-to-one>
</class>
</hibernate-mapping>
说明: 基于外键的1——N关联,外键存放在多的那一端,
1、 存放的一端(也就是多的一端)要增加many-to-one元素,column="映射到本表的字段名" (也可以不指定)
2、另一端使用set元素,使用key.column指定关联的外键列,在one-to-many中指明用以映射到关联类的属性;
第三步:配置文件(hibernate.cfg.xml)
<mapping resource="hibernate/test/xml/Employee.hbm.xml"></mapping>
<mapping resource="hibernate/test/xml/Department.hbm.xml"></mapping>
第四步:测试
public static void main(String[] args) {
// TODO Auto-generated method stub
Session session=null;
Transaction tx=null;
try {
session=HibernateUtil.getSession();
tx=session.beginTransaction();
Department department=new Department();
department.setDname("技术部");
department.setLocation("zhengzhou");
session.save(department);
Employee employee1=new Employee();
employee1.setName("张三");
Employee employee2=new Employee();
employee2.setName("李四");
employee1.setDepartment(department);
employee2.setDepartment(department);
session.save(employee1);
session.save(employee2);
tx.commit();
} catch (Exception e) {
// TODO: handle exception
if(tx!=null)
tx.rollback();
}
finally{
if(session!=null)
session.close();
}
}
(3)多对多映射
第一步:建立类(学生和课程是多对多的关系)
学生类:
public class StudentXML {
private int id;
private String name;
private Set<CourseXML> courseXMLs=new HashSet<CourseXML>();
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;
}
public void setCourseXMLs(Set<CourseXML> courseXMLs) {
this.courseXMLs = courseXMLs;
}
public Set<CourseXML> getCourseXMLs() {
return courseXMLs;
}
}
课程类:
public class CourseXML {
private int id;
private String name;
private Set<StudentXML> studentXMLs=new HashSet<StudentXML>();
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;
}
public Set<StudentXML> getStudentXMLs() {
return studentXMLs;
}
public void setStudentXMLs(Set<StudentXML> studentXMLs) {
this.studentXMLs = studentXMLs;
}
}
第二步:映射文件
学生类映射文件(StudentXML.hbm.xml):
<hibernate-mapping package="hibernate.test.domain">
<class name="StudentXML" table="studentXML" lazy="true">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="courseXMLs" table="stu_coursexml" cascade="save-update">
<!-- 指定关联的外键列 -->
<key column="studentId"/><!-- key.column指出本类提供中间表的字段-->
<many-to-many class="CourseXML" column="courseId"></many-to-many>
</set>
</class>
</hibernate-mapping>
课程类映射文件(CourseXML.hbm.xml):
<hibernate-mapping package="hibernate.test.domain">
<class name="CourseXML" table="courseXML" lazy="true">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="studentXMLs" table="stu_coursexml" cascade="save-update">
<key column="courseId"/> <!-- key.column指出本类提供中间表的字段-->
<many-to-many class="StudentXML" column="studentId"></many-to-many>
</set>
</class>
</hibernate-mapping>
说明: 基于外键的N——N关联,两个表的主键作为第三张表进行存储
1、 一端使用set元素,使用key.column指出本类提供中间表的字段,在many-to-many中指明用以映射到关联类的属性,而many-to-many中的column属性指的是class类在第三张表(中间表)中的字段;
2、另一端和前面一样,需要制定本类和关联类在第三张表中的属性。两者配置时要注意属性对应,第三张表的表名一样。
第三步:配置文件(hibernate.cfg.xml)
<mapping resource="hibernate/test/xml/CourseXML.hbm.xml"></mapping>
<mapping resource="hibernate/test/xml/StudentXML.hbm.xml"></mapping>
第四步:测试
public static void main(String[] args) {
// TODO Auto-generated method stub
Session session=null;
Transaction tx=null;
try {
session=HibernateAnnocationUtil.getSession();
tx=session.beginTransaction();
StudentXML student2=new StudentXML();
student2.setName("zhangsan");
StudentXML student22=new StudentXML();
student22.setName("liuyang");
CourseXML course=new CourseXML();
course.setName("语文");
//course.setName("数学");
HashSet<CourseXML> courses=new HashSet<CourseXML>();
courses.add(course);
student2.setCourseXMLs(courses);
student22.setCourseXMLs(courses);
session.save(student2);
session.save(student22);
tx.commit();
} catch (Exception e) {
// TODO: handle exception
if(tx!=null)
tx.rollback();
}
finally{
if(session!=null)
session.close();
}
}
(4)Cascade和inverse
详细见: http://www.cnblogs.com/amboyna/archive/2008/02/18/1072260.html
级联指的是当主控方执行操作时,关联对象(被动方)是否同步执行同一操作。
cascade定义的是关系两端对象到对象的级联关系;而inverse定义的是关系和对象的级联关系
Cascade:
all : 所有情况下均进行关联操作。
none:所有情况下均不进行关联操作。这是默认值。
save-update:在执行save/update/saveOrUpdate时进行关联操作。
delete:在执行delete时进行关联操作。
all的意思是save-update + delete
all-delete-orphan 的意思是当对象图中产生孤儿节点时,在数据库中删除该节点
Inverse:
只有集合标记(set/map/list/array/bag)才有inverse属性
commit后,这两个属性发挥作用的时机不同,hibernate会根据对pojo对象的改动,及cascade属性的设置,生成一系列的Action,比如UpdateAction,DeleteAction,InsertAction等,每个Action都有execute方法以执行对应的sql语句。待所有这些Action都生成好了后,hibernate再一起执行它们,在执行sql前,inverse属性起作用,
当inverse=true时,不执行sql;当inverse=false时,执行sql。 inverse的默认值为false,所以inverse属性默认会进行“关联更新”。