zoukankan      html  css  js  c++  java
  • Hibernate学习笔记

    Hibernate集合映射

    1. Set 
    2. List
    3. Map
    4. Array
    5. 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 (?, ?)
  • 相关阅读:
    Linux IO接口 监控 (iostat)
    linux 防火墙 命令
    _CommandPtr 添加参数 0xC0000005: Access violation writing location 0xcccccccc 错误
    Visual Studio自动关闭
    Linux vsftpd 安装 配置
    linux 挂载外部存储设备 (mount)
    myeclipse 9.0 激活 for win7 redhat mac 亲测
    英文操作系统 Myeclipse Console 乱码问题
    Linux 基本操作命令
    linux 查看系统相关 命令
  • 原文地址:https://www.cnblogs.com/heml/p/4732498.html
Copyright © 2011-2022 走看看