您的位置:首页 > 其它

Hibernate学习笔记

2015-08-22 15:50 483 查看

Hibernate集合映射

Set

List

Map

Array

Bag

Set集合

set元素不允许重复,常见的有HashSet、TreeSet、LinkedHashSet,HashSet中的元素是没有顺序的,TreeSet和LinkedHashSet中的元素是有序的

实体类User

package com.hml.domain;

import java.util.Set;

public class User {

private int id;
private String name;
private Set<String> address;// set集合存放地址

public int getId() {
return id;
}

public Set<String> getAddress() {
return address;
}

public void setAddress(Set<String> address) {
this.address = address;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}


User.hbm.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hml.domain">
<class name="User" table="t_user">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>

<!--
name: set集合对象
table:集合对象数据存储的表
key:外键的名称,对应的数据是User的主键
element:set集合中存储的数据
-->
<set name="address" table="t_user_address">
<key column="userId"></key>
<element column="address" type="string"></element>
</set>
</class>

</hibernate-mapping>


注意:hibernate中的集合在实体类中声明时应该声明为接口类型,因为Hibernate内部对集合类型进行了特殊处理。

Set集合hbm的配置文件如上,如果需要排序可以在set节点添加sort属性或者order-by属性指定排序,但是此时要求的Set集合是有序的集合,如:TreeSet。sort是内存排序,order-by是数据库排序,建议使用order-by。

List集合

List集合是有序的集合

实体类User

package com.hml.domain;

import java.util.List;

public class User {

private int id;
private String name;
private List<String> address; // List集合

public int getId() {
return id;
}

public List<String> getAddress() {
return address;
}

public void setAddress(List<String> address) {
this.address = address;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}


User.hbm.xml文件配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hml.domain">
<class name="User" table="t_user">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>

<!--
name: set集合对象
table:集合对象数据存储的表
key:外键的名称,对应的数据是User的主键
element:set集合中存储的数据
list-index:指定集合元素的顺序
-->
<list name="address" table="t_user_address">
<key column="userId"></key>
<list-index column="idx"></list-index>
<element column="address" type="string"></element>
</list>
</class>

</hibernate-mapping>


List集合的配置和Set类似,只是多了一个指定元素顺序的节点list-index

集合Map

Map集合存储key value 值对

User实体类

package com.hml.domain;

import java.util.Map;

public class User {

private int id;
private String name;
private Map<String, String> address;

public int getId() {
return id;
}

public Map<String, String> getAddress() {
return address;
}

public void setAddress(Map<String, String> address) {
this.address = address;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

}


User.hbm.xml文件的配置

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hml.domain">
<class name="User" table="t_user">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>

<!--
name: Map集合对象
table:集合对象数据存储的表
key:外键的名称,对应的数据是User的主键
element:Map集合中存储的数据
map-key:Map集合中key的映射
-->
<map name="address" table="t_user_address">
<key column="userid"></key>
<map-key column="key_" type="string"></map-key>
<element column="address" type="string"></element>
</map>
</class>

</hibernate-mapping>


Array数组的使用和List集合差不多只是使用的节点是array而已,Bag存储的元素可重复,但是是无序的,配置使用的是bag节点,实体中使用的是list集合。

多对一/一对多关系

这里用员工和部门举例,部门和员工的关系是一对多的关系,员工和部门的关系就是多对一的关系。

类图



Employee实体

package com.hml.domain;

public class Employee {

private Integer id;
private String name;
private Department department;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Department getDepartment() {
return department;
}

public void setDepartment(Department department) {
this.department = department;
}

}


Department实体

package com.hml.domain;

import java.util.HashSet;
import java.util.Set;

public class Department {

private Integer id;
private String name;
private Set<Employee> employees = new HashSet<Employee>();

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Set<Employee> getEmployees() {
return employees;
}

public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}

}


Employee.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hml.domain">
<class name="Employee" table="t_employee">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>

<!--
many-to-one:表示多对一的关系
column:指定外键的名称,可以省略,如果省略,则外键名称和name一致
class:指定一的一方是哪个类,可以省略,系统可以自动推断
-->
<many-to-one name="department" column="departmentid" class="Department"></many-to-one>
</class>

</hibernate-mapping>


Department.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hml.domain">
<class name="Department" table="t_department">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>

<!--
这里和普通集合的配置是一样的,只不过这里的key的column是多的一方的many-to-one column的值,
element元素变成了one-to-many,class的值是多的一方的全限定名称
-->
<set name="employees" >
<key column="departmentid"></key>
<one-to-many class="Employee"/>
</set>

</class>

</hibernate-mapping>


上面的例子是 多对一/一对多 的双向映射关系,也就是说两遍都可以维护关系。一般情况下为了效率,会让一的一方放弃维护关系,这个时候我们可以使用如下的配置

Department.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hml.domain">
<class name="Department" table="t_department">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>

<!--
这里和普通集合的配置是一样的,只不过这里的key的column是多的一方的many-to-one column的值,
element元素变成了one-to-many,class的值是多的一方的全限定名称

inverse: 默认为false,代表维护关系,如果为true则表示放弃维护关系,这时关系由另外一方维护
-->
<set name="employees" inverse="true">
<key column="departmentid"></key>
<one-to-many class="Employee"/>
</set>

</class>

</hibernate-mapping>


inverse:如果一的一方放弃维护关联关系,也就是inverse="true",那么对于一的一方进行删除,如果多的一方有关联的数据,那么会抛出异常,对于数据的加载不会存在影响

一对多和多对一可分为,单向和双向关系,单向是指有一方不能查询到对方,双向是指,彼此都可以查到对方。如果我们把Department employees属性去掉,那么对应关系就是一对多单向关联关系。

多对多的对应关系



Student实体类

package com.hml.domain;

import java.util.HashSet;
import java.util.Set;

public class Student {

private Integer id;
private String name;
private Set<Teacher> teachers = new HashSet<Teacher>();;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Set<Teacher> getTeachers() {
return teachers;
}

public void setTeachers(Set<Teacher> teachers) {
this.teachers = teachers;
}

}


Teacher实体类

package com.hml.domain;

import java.util.HashSet;
import java.util.Set;

public class Teacher {
private Integer id;
private String name;
private Set<Student> students = new HashSet<Student>();

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Set<Student> getStudents() {
return students;
}

public void setStudents(Set<Student> students) {
this.students = students;
}

}


Student.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hml.domain">
<class name="Student" table="t_student">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>

<!--
table:中间表的名称
key:中间表的外键,对应本对象的id
many-to-many:说明多对多的关系,class指明关联对象,column中间表中相对于关联对象的外键
-->
<set name="teachers" table="t_student_tearcher" inverse="false">
<key column="studentId"></key>
<many-to-many class="Teacher" column="teacherId"></many-to-many>
</set>
</class>

</hibernate-mapping>


Teacher.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hml.domain">
<class name="Teacher" table="t_teacher">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>

<!--
table:中间表的名称
key:中间表的外键,对应本对象的id
many-to-many:说明多对多的关系,class指明关联对象,column中间表中相对于关联对象的外键
inverse: true表示不维护关联关系,多对多的映射建议一方放弃维护关联关系
cascade:指定级联关系,这里设置为delete是级联删除的意思,也就是说删除teacher的同时级联删除该老师的学生,
可以避免由于不能维护关系而删除对象报异常,cascade有多种取值,实际使用的时候按照需求设置
-->
<set name="students" table="t_student_tearcher" inverse="true" cascade="delete">
<key column="teacherId"></key>
<many-to-many class="Student" column="studentId"></many-to-many>
</set>
</class>

</hibernate-mapping>


多对多的对应关系也分为单向和双向,单向就是通过一方查询不到另外一方。

一对一映射关系

基于主键的一对一映射关系:有一张表的主键就是外键

基于外键的一对一映射关系:在一张表中存在一个外键,这个外键是唯一的

基于外键的一对一映射关系

表结构:

Person表:



IdCard表:



IdCard表中有一个外键personid对应了person表中的主键。

Person类:

package com.hml.domain;

public class Person {
private Integer id;
private String name;

private IdCard idCard; // 关联的身份证

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public IdCard getIdCard() {
return idCard;
}

public void setIdCard(IdCard idCard) {
this.idCard = idCard;
}

@Override
public String toString() {
return "[Person:id=" + id + ", name=" + name + "]";
}

}


IdCard类

package com.hml.domain;

public class IdCard {
private Integer id;
private String number;

private Person person; // 关联的公民

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getNumber() {
return number;
}

public void setNumber(String number) {
this.number = number;
}

public Person getPerson() {
return person;
}

public void setPerson(Person person) {
this.person = person;
}

@Override
public String toString() {
return "[IdCard:id=" + id + ", number=" + number + "]";
}

}


Person.hbm.xml映射文件:

<?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="com.hml.domain">

<class name="Person" table="person">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"/>

<!-- idCard属性,IdCard类型。
表达的是本类与IdCard的一对一。
采用基于外键的一对一映射方式,本方无外键方。
property-ref属性:
写的是对方映射中外键列对应的属性名。
-->
<one-to-one name="idCard" class="IdCard" property-ref="person"/>

</class>

</hibernate-mapping>


IdCard.hbm.xml映射文件:

<?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="com.hml.domain">

<class name="IdCard" table="idCard">
<id name="id">
<generator class="native"></generator>
</id>
<property name="number"/>

<!-- person属性,Person类型。
表达的是本类与Person的一对一。
采用基于外键的一对一映射方式,本方有外键方。 -->
<many-to-one name="person" class="Person" column="personId" unique="true"></many-to-one>

</class>

</hibernate-mapping>


基于外键的一对一映射其中一张表中会存在一个外键,这个外键是另外一张表的主键。在没有外键的映射文件中我们使用标签one-to-one来映射,name属性是映射的java对象的属性, class指定了映射的类, property-ref指定另外一方java类中映射为外键的属性。在有主键的一方通过many-to-one标签进行映射,该映射需要注意的是必须加上unique="true"。

基于主键的一对一映射:

Person.hbm.xml配置文件:

<?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="com.hml.domain">

<class name="Person" table="person">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"/>

<!-- idCard属性,IdCard类型。
表达的是本类与IdCard的一对一。
采用基于主键的一对一映射方式,本方无外键方。
-->
<one-to-one name="idCard" class="IdCard"></one-to-one>

</class>

</hibernate-mapping>


IdCard.hbm.xml配置文件

<?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="com.hml.domain">

<class name="IdCard" table="idCard">
<id name="id">
<!-- 当使用基于主键的一对一映射时, 有外键方的主键生成策略一定要是foreign。
参数property: 生成主键值时所根据的属性对象。 -->
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="number" />

<!-- person属性,Person类型。 表达的是本类与Person的一对一。
采用基于主键的一对一映射方式,本方有外键方。 constrained="true"强制加上外键约束-->
<one-to-one name="person" class="Person" constrained="true"></one-to-one>
</class>

</hibernate-mapping>


基于主键的映射两边属性都使用one-to-one进行映射,不过在有外键的一方有些不同,有外键的一方主键生成策略一定是foreign,还有就是one-to-one标签中,constrained="true",代表必须加上外键约束。基于主键的映射在插入数据的时候,先插入没有外键的一方的数据,然后把主键当成另外一方的主键进行数据插入:

Hibernate: insert into person (name) values (?)
Hibernate: insert into idCard (number, id) values (?, ?)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: