hibernate 关系映射
one-to-one主要有三种实现方式
1.通过外键方式实现
以学生和电脑为例(Student-Computer)
建表sql语句:
Student.java:
Computer.java:
Student.hbm.xml:
Computer.hbm.xml:
测试类:
2.通过主键方式实现(一个表的主键由另一个表的主键决定),在这里Computer的主键由Student的主键决定。
Student.hbm.xml:
Comuter.hbm.xml:
TestMainKey.java:
3.通过关系表实现:
1.通过外键方式实现
以学生和电脑为例(Student-Computer)
建表sql语句:
- CREATEDATABASE`onetoone`
- CHARACTERSET'utf8';
- USE`onetoone`;
- DROPTABLEIFEXISTS`student`;
- CREATETABLE`student`(
- `id`int(11)NOTNULLauto_increment,
- `name`varchar(255)NOTNULL,
- PRIMARYKEY(`id`)
- )ENGINE=InnoDBDEFAULTCHARSET=utf8;
- DROPTABLEIFEXISTS`computer`;
- CREATETABLE`computer`(
- `id`int(11)NOTNULLauto_increment,
- `name`varchar(255)NOTNULL,
- `student_id`int(11),
- foreignkey(`student_id`)referencesstudent(`id`),
- PRIMARYKEY(`id`)
- )ENGINE=InnoDBDEFAULTCHARSET=utf8;
CREATE DATABASE `onetoone`
CHARACTER SET 'utf8';
USE `onetoone`;
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `computer`;
CREATE TABLE `computer` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`student_id` int(11) ,
foreign key (`student_id`) references student(`id`),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Student.java:
- packagecom.domain;
- publicclassStudentimplementsjava.io.Serializable{
- privateIntegerid;
- privateStringname;
- privateComputercomputer;
- publicStudent(){
- }
- publicStudent(Stringname){
- this.name=name;
- }
- publicIntegergetId(){
- returnthis.id;
- }
- publicvoidsetId(Integerid){
- this.id=id;
- }
- publicStringgetName(){
- returnthis.name;
- }
- publicvoidsetName(Stringname){
- this.name=name;
- }
- publicComputergetComputer(){
- returncomputer;
- }
- publicvoidsetComputer(Computercomputer){
- this.computer=computer;
- }
- }
package com.domain;
public class Student implements java.io.Serializable {
private Integer id;
private String name;
private Computer computer;
public Student() {
}
public Student(String name) {
this.name = name;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Computer getComputer() {
return computer;
}
public void setComputer(Computer computer) {
this.computer = computer;
}
}
Computer.java:
- packagecom.domain;
- publicclassComputerimplementsjava.io.Serializable{
- privateIntegerid;
- privateStudentstudent;
- privateStringname;
- publicComputer(){
- }
- publicComputer(Stringname){
- this.name=name;
- }
- publicComputer(Studentstudent,Stringname){
- this.student=student;
- this.name=name;
- }
- publicIntegergetId(){
- returnthis.id;
- }
- publicvoidsetId(Integerid){
- this.id=id;
- }
- publicStudentgetStudent(){
- returnthis.student;
- }
- publicvoidsetStudent(Studentstudent){
- this.student=student;
- }
- publicStringgetName(){
- returnthis.name;
- }
- publicvoidsetName(Stringname){
- this.name=name;
- }
- }
package com.domain;
public class Computer implements java.io.Serializable {
private Integer id;
private Student student;
private String name;
public Computer() {
}
public Computer(String name) {
this.name = name;
}
public Computer(Student student, String name) {
this.student = student;
this.name = name;
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public Student getStudent() {
return this.student;
}
public void setStudent(Student student) {
this.student = student;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
Student.hbm.xml:
- <?xmlversion="1.0"encoding="utf-8"?>
- <!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <classname="com.domain.Student"table="student"catalog="onetoone">
- <idname="id"type="java.lang.Integer">
- <columnname="id"/>
- <generatorclass="native"/>
- </id>
- <propertyname="name"type="java.lang.String">
- <columnname="name"not-null="true"/>
- </property>
- <!--class可以不写,因为根据name的值computer(属性),会通过反射自动找到属于哪个类的-->
- <one-to-onecascade="delete,save-update"name="computer"class="com.domain.Computer"property-ref="student"></one-to-one>
- </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="com.domain.Student" table="student" catalog="onetoone">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="name" not-null="true" />
</property>
<!-- class可以不写,因为根据name的值computer(属性),会通过反射自动找到属于哪个类的 -->
<one-to-one cascade="delete,save-update" name="computer" class="com.domain.Computer" property-ref="student"></one-to-one>
</class>
</hibernate-mapping>
Computer.hbm.xml:
- <?xmlversion="1.0"encoding="utf-8"?>
- <!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <classname="com.domain.Computer"table="computer"catalog="onetoone">
- <idname="id"type="java.lang.Integer">
- <columnname="id"/>
- <generatorclass="native"/>
- </id>
- <propertyname="name"type="java.lang.String">
- <columnname="name"not-null="true"/>
- </property>
- <!--many开头的是代表该表持有外键-->
- <many-to-onename="student"class="com.domain.Student"unique="true">
- <columnname="student_id"/>
- </many-to-one>
- </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="com.domain.Computer" table="computer" catalog="onetoone">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="name" not-null="true" />
</property>
<!-- many开头的是代表该表持有外键 -->
<many-to-one name="student" class="com.domain.Student" unique="true">
<column name="student_id" />
</many-to-one>
</class>
</hibernate-mapping>
测试类:
- packagecom.domain;
- importorg.hibernate.Query;
- importorg.hibernate.Session;
- importcom.util.HibernateSessionFactory;
- publicclassTest{
- publicstaticvoidmain(String[]args){
- Sessionsession=HibernateSessionFactory.getSession();
- //save
- Studentstudent=newStudent();
- student.setName("student9");
- Computercomputer=newComputer();
- computer.setName("Intel9");
- //computer.setStudent(student)和student.setComputer(computer);都必须要
- computer.setStudent(student);
- student.setComputer(computer);
- session.save(student);
- /**
- 执行的sql:
- Hibernate:insertintoonetoone.student(name)values(?)
- Hibernate:insertintoonetoone.computer(name,student_id)values(?,?)
- */
- //
- session.beginTransaction().commit();
- //query
- //Stringhql="fromStudentwherename=?";
- //Queryquery=session.createQuery(hql);
- //query.setString(0,"student3");
- //
- //Studentstudent=(Student)query.uniqueResult();
- //System.out.println(student.getId()+":"+student.getComputer().getName());
- //delete
- //Studentstudent=(Student)session.load(Student.class,newInteger(1));
- //session.delete(student);
- //session.beginTransaction().commit();
- /**
- 执行的sql为:
- Hibernate:selectstudent0_.idasid0_1_,student0_.nameasname0_1_,computer1_.idasid1_0_,computer1_.nameasname1_0_,computer1_.student_idasstudent3_1_0_fromonetoone.studentstudent0_leftouterjoinonetoone.computercomputer1_onstudent0_.id=computer1_.student_idwherestudent0_.id=?
- Hibernate:deletefromonetoone.computerwhereid=?
- Hibernate:deletefromonetoone.studentwhereid=?
- */
- session.close();
- }
- }
package com.domain;
import org.hibernate.Query;
import org.hibernate.Session;
import com.util.HibernateSessionFactory;
public class Test {
public static void main(String[] args){
Session session = HibernateSessionFactory.getSession();
//save
Student student = new Student();
student.setName("student9");
Computer computer = new Computer();
computer.setName("Intel 9");
//computer.setStudent(student)和student.setComputer(computer);都必须要
computer.setStudent(student);
student.setComputer(computer);
session.save(student);
/**
执行的sql:
Hibernate: insert into onetoone.student (name) values (?)
Hibernate: insert into onetoone.computer (name, student_id) values (?, ?)
*/
//
session.beginTransaction().commit();
//query
// String hql = "from Student where name=?";
// Query query = session.createQuery(hql);
// query.setString(0, "student3");
//
// Student student = (Student)query.uniqueResult();
// System.out.println(student.getId() + " : " + student.getComputer().getName());
//delete
// Student student = (Student)session.load(Student.class, new Integer(1));
// session.delete(student);
// session.beginTransaction().commit();
/**
执行的sql为:
Hibernate: select student0_.id as id0_1_, student0_.name as name0_1_, computer1_.id as id1_0_, computer1_.name as name1_0_, computer1_.student_id as student3_1_0_ from onetoone.student student0_ left outer join onetoone.computer computer1_ on student0_.id=computer1_.student_id where student0_.id=?
Hibernate: delete from onetoone.computer where id=?
Hibernate: delete from onetoone.student where id=?
*/
session.close();
}
}
2.通过主键方式实现(一个表的主键由另一个表的主键决定),在这里Computer的主键由Student的主键决定。
Student.hbm.xml:
- <?xmlversion="1.0"encoding="utf-8"?>
- <!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <classname="com.domain.Student"table="student"catalog="onetoone">
- <idname="id"type="java.lang.Integer">
- <columnname="id"/>
- <generatorclass="native"/>
- </id>
- <propertyname="name"type="java.lang.String">
- <columnname="name"not-null="true"/>
- </property>
- <!--class可以不写,因为根据name的值computer(属性),会通过反射自动找到属于哪个类的
- <one-to-onecascade="delete,save-update"name="computer"class="com.domain.Computer"property-ref="student"></one-to-one>
- -->
- <one-to-onename="computer"/>
- </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="com.domain.Student" table="student" catalog="onetoone">
<id name="id" type="java.lang.Integer">
<column name="id" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="name" not-null="true" />
</property>
<!-- class可以不写,因为根据name的值computer(属性),会通过反射自动找到属于哪个类的
<one-to-one cascade="delete,save-update" name="computer" class="com.domain.Computer" property-ref="student"></one-to-one>
-->
<one-to-one name="computer"/>
</class>
</hibernate-mapping>
Comuter.hbm.xml:
- <?xmlversion="1.0"encoding="utf-8"?>
- <!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/HibernateMappingDTD3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping>
- <classname="com.domain.Computer"table="computer"catalog="onetoone">
- <idname="id"type="java.lang.Integer">
- <columnname="id"/>
- <!--generatorclass="native"/-->
- <!--Computer的主键由Student的主键决定,可以看成是外键-->
- <generatorclass="foreign">
- <paramname="property">student</param>
- </generator>
- </id>
- <propertyname="name"type="java.lang.String">
- <columnname="name"not-null="true"/>
- </property>
- <!--many开头的是代表该表持有外键
- <many-to-onename="student"class="com.domain.Student"unique="true">
- <columnname="student_id"/>
- </many-to-one>-->
- <one-to-onename="student"/>
- </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="com.domain.Computer" table="computer" catalog="onetoone">
<id name="id" type="java.lang.Integer">
<column name="id" />
<!--generator class="native" /-->
<!--Computer的主键由Student的主键决定,可以看成是外键-->
<generator class="foreign">
<param name="property">student</param>
</generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" not-null="true" />
</property>
<!-- many开头的是代表该表持有外键
<many-to-one name="student" class="com.domain.Student" unique="true">
<column name="student_id" />
</many-to-one> -->
<one-to-one name="student"/>
</class>
</hibernate-mapping>
TestMainKey.java:
- packagecom.domain;
- importorg.hibernate.Session;
- importcom.util.HibernateSessionFactory;
- publicclassTestMainKey{
- publicstaticvoidmain(String[]args){
- Sessionsession=HibernateSessionFactory.getSession();
- //save
- Studentstudent=newStudent();
- student.setName("student15");
- Computercomputer=newComputer();
- computer.setName("Intel15");
- computer.setStudent(student);
- //student.setComputer(computer);
- //因为save2个表,所以不需要双向赋值
- session.save(student);
- session.save(computer);
- session.beginTransaction().commit();
- session.close();
- }
- }
package com.domain;
import org.hibernate.Session;
import com.util.HibernateSessionFactory;
public class TestMainKey {
public static void main(String[] args){
Session session = HibernateSessionFactory.getSession();
//save
Student student = new Student();
student.setName("student15");
Computer computer = new Computer();
computer.setName("Intel 15");
computer.setStudent(student);
// student.setComputer(computer);
//因为save 2个表,所以不需要双向赋值
session.save(student);
session.save(computer);
session.beginTransaction().commit();
session.close();
}
}
3.通过关系表实现:
- DROPTABLEIFEXISTS`st`;
- createtablestu_com(
- stu_idintnotnull,
- com_idintnotnull
- )ENGINE=InnoDBDEFAULTCHARSET=utf8;
DROP TABLE IF EXISTS `st`;
create table stu_com(
stu_id int not null,
com_id int not null
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
- <!--optional="true"的意思是只有当stu_id和com_id都不为空时才在关系表里插入。这样也会插入
- 2遍,所以需要inverse="true"把一方设置为虚的。即不让插入到关系表中-->
- <jointable="stu-com"optional="true"inverse="true">
- <keycolumn="com_id"/>
- <many-to-onename="student"column="stu_id"unique="true"/>
- </join>
<!--optional="true"的意思是只有当stu_id 和 com_id 都不为空时才在关系表里插入。这样也会插入
2遍,所以需要inverse="true"把一方设置为虚的。即不让插入到关系表中-->
<join table="stu-com" optional="true" inverse="true">
<key column="com_id"/>
<many-to-one name="student" column="stu_id" unique="true"/>
</join>