Hibernate4

第一讲 Hibernate简介


  • Hibernate是一个轻量级、ORM的框架。完成数据的持久化。是对jdbc的封装,简化jdbc操作。使用Hibernate后,不需要编写Sql语句,是一个全自动的持久化框架。使用Hibernate后,可以跨数据库平台。提高开发效率。
  • 持久化:就是数据从瞬时状态变为持久状态的过程。
  • ORMObject Relational Mapping,对象关系映射.使得操作关系可以像操作对象一样方便。
    Hibernate_orm.PNG
  • 结构体系
    结构体系.PNG

第二讲 helloworld

  • 使用hibernate进行helloworld程序开发,步骤:
  1. 新建Java项目

  2. 导入hibernate jar包

  3. 新建数据库表

  4. 新建pojo对象

  5. 编写User.hbm.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <?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>
    <class name="com.zhuchuli.vo.User" table="t_user">
    <!-- 主键映射 -->
    <id name="id" column="id" type="int">
    <!-- 主键生成策略 -->
    <generator class="native"/>
    </id>
    <property name="name" column="name" type="java.lang.String"></property>
    <property name="age" column="age" type="int"></property>
    </class>
    </hibernate-mapping>
  6. src包下新建hibernate.cfg.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>
    <session-factory>
    <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost:3306/hibernate4?serverTimezone=UTC</property>
    <property name="connection.username">root</property>
    <property name="connection.password">123456</property>
    <!-- 指定数据库的方言 -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <mapping resource="com/zhuchuli/vo/User.hbm.xml"/>
    </session-factory>
    </hibernate-configuration>
  7. 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    package com.zhuchuli.test;

    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.service.ServiceRegistry;

    import com.zhuchuli.vo.User;

    public class HiberatorTest {
    public static void main(String[] args) {
    //1.读取hibrator.cfg.xml配置文件
    Configuration cfg=new Configuration().configure();
    //2.创建服务注册
    ServiceRegistry registery=new StandardServiceRegistryBuilder()
    .applySettings(cfg.getProperties())
    .build();
    //3.新建sessionFactory对象
    SessionFactory factory=cfg.buildSessionFactory(registery);

    //4.创建session对象
    Session session=factory.openSession();
    //5.获取数据
    User user=(User) session.get(User.class,1);
    System.out.println(user);
    //6.释放资源
    session.close();
    factory.close();
    }
    }

第三讲 配置文件讲解

  • hibernate.cfg.xmlhibernate的主配置文件,Configuration读取的也是该对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <hibernate-configuration>

    <session-factory>
    <!--
    数据库连接信息
    根据不同的数据库,要配置不同参数信息。
    -->
    <property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost:3306/hibernate4?serverTimezone=UTC</property>
    <property name="connection.username">root</property>
    <property name="connection.password">123456</property>
    <!-- 通用配置 -->
    <!-- 指定数据库的方言 -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <!-- 打印sql语句 -->
    <property name="show_sql">true</property>
    <!-- 格式化sql语句 -->
    <property name="format_sql">true</property>
    <!-- 映射文件信息 -->
    <mapping resource="com/zhuchuli/vo/User.hbm.xml"/>
    </session-factory>
    </hibernate-configuration>
  • 映射文件:Xxx-hbm.xml

    • 非关系型数据库:MongoDBHBaseredis
    • 《组成原理》《编译原理》
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    <?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">
    <!-- package用于指定类所在的包,如果不指定,那么在指定class的name时,需要指定完全限定名 -->
    <hibernate-mapping package="com.zhuchuli.vo">
    <!--
    class指定类的映射信息
    name指定类,如果没有指定package时需要使用完全限定名
    table指定类对应的数据库的数据表名,如果不指定,默认和类型相同。
    schema:指定模式
    -->
    <class name="User" table="t_user" schema="">
    <!--
    主键映射
    在hibernate中,类所对应的表必须要有主键
    name:为类所的属性名
    column:是属性名所对应的表的字段名称,类型是属性的类型
    column默认很属性名一致,类型默认和属性的类型一致。
    length 指定长度
    -->
    <id name="id" column="id" type="int">
    <!--
    主键生成策略

    Oracle数据库 自增生成策略
    <generator class="sequence">
    <param name="sequence">user_seq</param>
    </generator>
    UUID:生成的字符串唯一
    hilo:使用一个高/低位算法高效生成long,short或int类型的标识符
    assign:自己输入主键
    forign:

    -->

    <generator class="native"/>
    </id>
    <!-- property 指定属性的映射 -->
    <property name="name" column="name" type="java.lang.String"></property>
    <property name="age" column="age" type="int"></property>
    </class>
    </hibernate-mapping>

第四讲 工具类及hibernate crud操作

  • 工具类Util

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    package com.zhuchuli.util;

    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.service.ServiceRegistry;

    public class HibernateUtil {
    private static Configuration cfg=null;
    private static ServiceRegistry registery=null;
    private static SessionFactory factory=null;
    private static ThreadLocal<Session> sessionLocal=null;
    static {
    cfg=new Configuration().configure();
    registery=new StandardServiceRegistryBuilder()
    .applySettings(cfg.getProperties())
    .build();
    /***
    * sessionFactory是一个重量级对象,在一个应用中只需一个即可。是一个
    * 进程级别对象,可以在集群中使用。
    * 操作完后一般不会释放资源。
    */
    factory=cfg.buildSessionFactory(registery);
    sessionLocal=new ThreadLocal<Session>();
    }
    public static Session getSession() {
    if( sessionLocal.get()!=null && !sessionLocal.get().isOpen()) {
    sessionLocal.set(null);
    }
    if(sessionLocal.get() == null) {
    sessionLocal.set(factory.openSession());
    }
    return sessionLocal.get();
    }
    //释放资源
    public static void close() {
    if(sessionLocal.get()!=null) {
    sessionLocal.get().close();
    sessionLocal.set(null);

    }
    }
    }
  • crud操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    package com.zhuchuli.hibernate.test;

    import org.hibernate.Session;
    import org.hibernate.Transaction;

    import com.zhuchuli.util.HibernateUtil;
    import com.zhuchuli.vo.User;

    public class HibernateTest {
    public static void main(String[] args) {

    }
    //删除 先查后删除。
    private static void delete() {
    Session session=null;
    Transaction tx=null;
    try {
    //获取Session对象
    session= HibernateUtil.getSession();
    //获取事务并且开启事务
    tx= session.beginTransaction();
    User user=(User) session.get(User.class, 4);
    //删除
    session.delete(user);
    //提交事务
    tx.commit();
    } catch (Exception e) {
    e.printStackTrace();
    if(tx!=null) {
    tx.rollback();
    }
    }finally {
    HibernateUtil.close();
    }
    }
    //修改数据 先查在修改最后再删除
    private static void update() {
    Session session=null;
    Transaction tx=null;
    try {
    //获取Session对象
    session= HibernateUtil.getSession();
    //获取事务并且开启事务
    tx= session.beginTransaction();
    User user=(User) session.get(User.class, 4);
    System.out.println(user);
    user.setName("小六六");
    //修改
    session.save(user);
    //提交事务
    tx.commit();
    } catch (Exception e) {
    e.printStackTrace();
    if(tx!=null) {
    tx.rollback();
    }
    }finally {
    HibernateUtil.close();
    }
    }
    //
    //增加数据
    private static void save() {
    Session session=null;
    Transaction tx=null;
    try {
    //获取Session对象
    session= HibernateUtil.getSession();
    //获取事务并且开启事务
    tx= session.beginTransaction();
    /* 下面两句话等同上面一句话
    Transaction tx=session.getTransaction();
    tx.begin();
    */
    User user = new User();
    user.setName("刘德华");
    user.setAge(53);
    //保存数据
    session.save(user);
    //提交事务
    tx.commit();
    } catch (Exception e) {
    e.printStackTrace();
    if(tx!=null) {
    tx.rollback();
    }
    }finally {
    HibernateUtil.close();
    }
    }
    }

第五讲

  • 软件工程步骤:
    • 需要分析、概要分析、详细分析、编程、测试、发布
  • 测试:
    • 黑盒测试:工人测试。
    • 白盒测试:Junit,需要编码实现
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    package com.zhuchuli.test;

    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;

    import com.zhuchuli.util.HibernateUtil;
    import com.zhuchuli.vo.User;

    public class HibernateTest {
    private Session session=null;
    private Transaction tx=null;
    @Before
    public void setUp() {
    try {
    //获取Session对象
    session = HibernateUtil.getSession();
    //获取事务并且开启事务
    tx = session.beginTransaction();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    @After
    public void tear() {
    HibernateUtil.close();
    }
    @Test
    public void testSave() {
    try {
    User user = new User();
    user.setName("张学友");
    user.setAge(53);
    //保存数据
    session.save(user);
    //提交事务
    tx.commit();
    } catch (Exception e) {
    e.printStackTrace();
    if(tx!=null) {
    tx.rollback();
    }
    }
    }
    }

第六讲 对象生命周期

  1. 对象生命周期图

对象生命周期.png

  1. 两种路线
    • new —> 瞬时状态 —> save() —> 持久状态 —> close() —> 游离状态。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    //测试对象生命周期:第一条线路
    @Test
    public void testSession1() {
    User user=null;
    try {
    //user处于瞬时状态
    user = new User();
    user.setName("kkk");
    user.setAge(40);
    //user处于持久状态
    //对象处于持久状态时被session管理
    session.save(user);
    //对象处于持久状态时,提交事务前会将session中对象与数据库中的记录进行脏数据检查,如果不一致则进行数据同步。
    //user.setAge(23);//此时会自动调用update()
    //提交事务
    tx.commit();
    } catch (Exception e) {
    e.printStackTrace();
    if(tx!=null) {
    tx.rollback();
    }
    }
    //请除指定对象 ----> session不再管理user
    //user此时处于游离状态,可能会把垃圾回收站回收。
    session.evict(user);
    //close关闭session
    session.close();
    //clear清楚session所有对象
    }
  • Get —> 持久状态 —> clear —> 游离状态 —> update() —> 持久状态 –> delete() —> 瞬时状态
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//测试对象生命周期:第二条线路
@Test
public void testSession2() {
User user=null;
try {
//user对象被session管理,处于持久状态
user=(User) session.get(User.class, 1);
//调用clear后,session不在管理user,user处理游离状态
session.clear();
user.setName("ddd");//此时处于游离状态,所有数据库的数据不会发生改变
session.update(user);//重回持久状态,user对象被session管理.
session.delete(user);//删除后user对象处于瞬时状态。
tx.commit();
} catch (Exception e) {
e.printStackTrace();

}

}
  1. 总结

    • 瞬时状态 session没有,数据库没有
    • 持久状态 session有,数据库有,在该状态下会进行脏数据的读取
    • 游离状态 session没有,数据库有

    第七讲 hibernate与struts2框架的整合

    第八讲 关联映射之单向多对一

  2. SchemaExport工具类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /***
    * 将对象信息 转换为 关系信息
    */
    @Test
    public void testCreateDB() {
    Configuration cfg=new Configuration().configure();
    //使得hibernate映射信息转化为ddl(数据库定义语言)
    SchemaExport se = new SchemaExport(cfg);
    //第一参数:是否打印ddl语句
    //第二个参数:是否将ddl到数据库执行
    se.create(true, true);
    }
  3. 通用配置实现hbm to ddl

    1
    2
    3
    4
    5
    6
    7
    <!-- 
    hbm2ddl.auto:该属性用于配置 是否将映射信息转换为关系信息
    create:每次执行都会删除表再创建表
    update:先检查数据库中表是否存在,如果不存在则先创建表,通常使用update
    create-drop:
    -->
    <property name="hbm2ddl.auto">create</property>
  4. 类与类之间的关系

    • 依赖 –> 关联 –> 组合 –> 聚合
  5. 学生和班级的信息是一个多对一的关系

    • 表结构
      关联.PNG
    • 类结构:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    package com.zhuchuli.vo;

    import java.io.Serializable;

    /***
    * 学生类
    * @author 朱楚利
    *
    */
    public class Student implements Serializable{
    private int id;
    private String name;
    private int age;
    private String sex;
    //学生所对应的班级
    private Cluss cluss;
    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 int getAge() {
    return age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public String getSex() {
    return sex;
    }
    public void setSex(String sex) {
    this.sex = sex;
    }
    public Cluss getCluss() {
    return cluss;
    }
    public void setCluss(Cluss cluss) {
    this.cluss = cluss;
    }

    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.zhuchuli.vo;

import java.io.Serializable;

/***
* 班级类
* @author 朱楚利
*
*/
public class Cluss implements Serializable{
private int id;
private String name;
private String address;
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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}

}
  1. 映射文件
    • 班级映射文件:Cluss.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <hibernate-mapping package="com.zhuchuli.vo">
    <class name="Cluss" table="t_class">
    <id name="id">
    <generator class="native"></generator>
    </id>
    <property name="name"></property>
    <property name="address"></property>
    </class>
    </hibernate-mapping>
  • 学生映射文件:Student.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<hibernate-mapping package="com.zhuchuli.vo">
<class name="Student" table="t_student" schema="">
<id name="id">
<generator class="native"/>
</id>
<!-- property 指定属性的映射 -->
<property name="name"/>
<property name="age" />
<property name="sex" />
<!--
多对一关联映射
name:属性名
column:外键名
-->
<many-to-one name="cluss" column="cluss_id"></many-to-one>
</class>
</hibernate-mapping>
  • hibernate.cfg.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<hibernate-configuration>

<session-factory>
<!--
数据库连接信息
根据不同的数据库,要配置不同参数信息。
-->
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost:3306/hibernate4?serverTimezone=UTC&amp;characterEncoding=UTF8</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<!-- 通用配置 -->
<!-- 指定数据库的方言 -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 打印sql语句 -->
<property name="show_sql">true</property>
<!-- 格式化sql语句 -->
<property name="format_sql">true</property>
<!--
hbm2ddl.auto:该属性用于配置 是否将映射信息转换为关系信息
create:每次执行都会删除表再创建表
update:先检查数据库中表是否存在,如果不存在则先创建表,通常使用update
create-drop:
-->
<property name="hbm2ddl.auto">update</property>
<!-- 映射文件信息 -->
<mapping resource="com/zhuchuli/vo/Student.hbm.xml"/>
<mapping resource="com/zhuchuli/vo/Cluss.hbm.xml"/>
</session-factory>
</hibernate-configuration>
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@Test
public void testCreateDB() {
Configuration cfg=new Configuration().configure();
//使得hibernate映射信息转化为ddl(数据库定义语言)
SchemaExport se = new SchemaExport(cfg);
//第一参数:是否打印ddl语句
//第二个参数:是否将ddl到数据库执行
se.create(true, true);
}

@Test
public void testInit() {
try {
Cluss c1=new Cluss();
c1.setName("208");
c1.setAddress("B-2");
Cluss c2=new Cluss();
c2.setName("301");
c2.setAddress("B-3");
session.save(c1);
session.save(c2);
Student s1=new Student();
s1.setName("张三");
s1.setAge(23);
s1.setSex("男");
//设置学生的外键,不高不设置,保存的学生将没有外键值
s1.setCluss(c1);
Student s2=new Student();
s2.setName("李四");
s2.setAge(22);
s2.setSex("男");
//设置学生的外键,不高不设置,保存的学生将没有外键值
s2.setCluss(c2);
Student s3=new Student();
s3.setName("王小蒙");
s3.setAge(20);
s3.setSex("女");
//设置学生的外键,不高不设置,保存的学生将没有外键值
s3.setCluss(c1);
session.save(s1);
session.save(s2);
session.save(s3);
tx.commit(); //提交5个事务,保存数据
} catch (Exception e) {
e.printStackTrace();
if(tx!=null)tx.rollback();
}
}
//关联映射主要为查询服务 当具有多对一关系时,在获取多的一段的信息时可以直接获取一的一端的信息
@Test
public void testGet() {
Student student=(Student)session.get(Student.class, 1);

System.out.println(student.getName()+"---->"+student.getAge());
System.out.println("---------------------");
System.out.println(student.getCluss().getName()+"---->"+student.getCluss().getAddress());
}

第九讲 关联映射之单向一对多关联

  • 还是考虑学生和班级的关系。有的时候查询班级需要将班级对应的学生信息一起查询,这个时候使用一对多的关联比较方便。
  • 表结构:与上面一样。
  • 类结构:
    • 班级类 Cluss.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class Cluss implements Serializable{
    private int id;
    private String name;
    private String address;
    private Set<Student> students=new HashSet<Student>();
    public Set<Student> getStudents() {
    return students;
    }
    public void setStudents(Set<Student> students) {
    this.students = students;
    }
    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 getAddress() {
    return address;
    }
    public void setAddress(String address) {
    this.address = address;
    }

    }
  • 学生类 Student.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.zhuchuli.vo;

import java.io.Serializable;
public class Student implements Serializable{
private int id;
private String name;
private int age;
private String sex;
//学生所对应的班级

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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}

}
  • 映射文件
  • Student.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
<hibernate-mapping package="com.zhuchuli.vo">
<class name="Student" table="t_student" schema="">
<id name="id">
<generator class="native"/>
</id>
<!-- property 指定属性的映射 -->
<property name="name"/>
<property name="age" />
<property name="sex" />

</class>
</hibernate-mapping>
  • Cluss.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<hibernate-mapping package="com.zhuchuli.vo">
<class name="Cluss" table="t_class">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<property name="address"></property>
<!-- 1对多的关联 name为属性名 -->
<set name="students">
<!-- column指定外键名 -->
<key column="cluss_id"></key>
<!-- 指定多的一端的类型 -->
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
public class HibernateTest {
private Session session=null;
private Transaction tx=null;
@Before
public void setUp() {
try {
//获取Session对象
session = HibernateUtil.getSession();
//获取事务并且开启事务
tx = session.beginTransaction();
} catch (Exception e) {
e.printStackTrace();
}
}
@After
public void tear() {
HibernateUtil.close();
}
/***
* 将对象信息 转换为 关系信息
*/
@Test
public void testCreateDB() {
Configuration cfg=new Configuration().configure();
//使得hibernate映射信息转化为ddl(数据库定义语言)
SchemaExport se = new SchemaExport(cfg);
//第一参数:是否打印ddl语句
//第二个参数:是否将ddl到数据库执行
se.create(true, true);
}
/***
* 一对多关联时保存数据会多出n挑更新语句,降低效率
* 一般不会使用一对多来关联映射
*/
@Test
public void testInit() {
try {
Cluss c1=new Cluss();
c1.setName("208");
c1.setAddress("B-2");
Cluss c2=new Cluss();
c2.setName("301");
c2.setAddress("B-3");
session.save(c1);
session.save(c2);
Student s1=new Student();
s1.setName("张三");
s1.setAge(23);
s1.setSex("男");
//设置学生的外键,如果不设置,保存的学生将没有外键值

Student s2=new Student();
s2.setName("李四");
s2.setAge(22);
s2.setSex("男");
//设置学生的外键,不高不设置,保存的学生将没有外键值

Student s3=new Student();
s3.setName("王小蒙");
s3.setAge(20);
s3.setSex("女");
//设置学生的外键,不高不设置,保存的学生将没有外键值

session.save(s1);
session.save(s2);
session.save(s3);
c1.getStudents().add(s1);
c1.getStudents().add(s3);
c2.getStudents().add(s2);

tx.commit(); //提交5个事务,保存数据
} catch (Exception e) {
e.printStackTrace();
if(tx!=null)tx.rollback();
}
}
//关联映射主要为查询服务 当具有多对一关系时,在获取多的一段的信息时可以直接获取一的一端的信息
@Test
public void testGet() {

Cluss c1=(Cluss) session.get(Cluss.class, 1);
System.out.println(c1.getName()+"--->" +c1.getAddress());
System.out.println("--------------");
for (Student s : c1.getStudents()) {
System.out.println(s.getName() + "--->" + s.getAge());
}

}

}

关联映射之双向多对一

  1. 学生和班级的双向关联,表结构,与上面表结构一样
  2. 类结构
    • Cluss.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class Cluss implements Serializable{
    private int id;
    private String name;
    private String address;
    private Set<Student> students=new HashSet<Student>();
    public Set<Student> getStudents() {
    return students;
    }
    public void setStudents(Set<Student> students) {
    this.students = students;
    }
    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 getAddress() {
    return address;
    }
    public void setAddress(String address) {
    this.address = address;
    }

    }
  • Student.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Student implements Serializable{
private int id;
private String name;
private int age;
private String sex;
//学生所对应的班级
private Cluss cluss;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Cluss getCluss() {
return cluss;
}
public void setCluss(Cluss cluss) {
this.cluss = cluss;
}

}
  1. 映射文件
    • Cluss.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- package用于指定类所在的包,如果不指定,那么在指定class的name时,需要指定完全限定名 -->
    <hibernate-mapping package="com.zhuchuli.vo">

    <class name="Cluss" table="t_class">
    <id name="id">
    <generator class="native"></generator>
    </id>
    <property name="name"></property>
    <property name="address"></property>
    <!-- 1对多的关联 name为属性名 -->
    <set name="students" inverse="true">
    <!-- column指定外键名 -->
    <key column="cluss_id"></key>
    <!-- 指定多的一端的类型 -->
    <one-to-many class="Student"/>
    </set>
    </class>
    </hibernate-mapping>
  • Student.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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">
<!-- package用于指定类所在的包,如果不指定,那么在指定class的name时,需要指定完全限定名 -->
<hibernate-mapping package="com.zhuchuli.vo">
<class name="Student" table="t_student" schema="">
<id name="id">
<generator class="native"/>
</id>
<!-- property 指定属性的映射 -->
<property name="name"/>
<property name="age" />
<property name="sex" />
<many-to-one name="cluss" column="cluss_id"></many-to-one>
</class>
</hibernate-mapping>
  1. 测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    package com.zhuchuli.test;

    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.tool.hbm2ddl.SchemaExport;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;

    import com.zhuchuli.util.HibernateUtil;
    import com.zhuchuli.vo.Cluss;
    import com.zhuchuli.vo.Student;


    public class HibernateTest {
    private Session session=null;
    private Transaction tx=null;
    @Before
    public void setUp() {
    try {
    //获取Session对象
    session = HibernateUtil.getSession();
    //获取事务并且开启事务
    tx = session.beginTransaction();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    @After
    public void tear() {
    HibernateUtil.close();
    }
    /***
    * 将对象信息 转换为 关系信息
    */
    @Test
    public void testCreateDB() {
    Configuration cfg=new Configuration().configure();
    //使得hibernate映射信息转化为ddl(数据库定义语言)
    SchemaExport se = new SchemaExport(cfg);
    //第一参数:是否打印ddl语句
    //第二个参数:是否将ddl到数据库执行
    se.create(true, true);
    }
    /***
    * 一对多关联时保存数据会多出n挑更新语句,降低效率
    * 一般不会使用一对多来关联映射
    */
    @Test
    public void testInit() {
    try {
    Cluss c1=new Cluss();
    c1.setName("208");
    c1.setAddress("B-2");
    Cluss c2=new Cluss();
    c2.setName("301");
    c2.setAddress("B-3");
    session.save(c1);
    session.save(c2);
    Student s1=new Student();
    s1.setName("张三");
    s1.setAge(23);
    s1.setSex("男");
    //设置学生的外键,如果不设置,保存的学生将没有外键值
    s1.setCluss(c1);
    Student s2=new Student();
    s2.setName("李四");
    s2.setAge(22);
    s2.setSex("男");
    //设置学生的外键,不高不设置,保存的学生将没有外键值
    s2.setCluss(c2);
    Student s3=new Student();
    s3.setName("王小蒙");
    s3.setAge(20);
    s3.setSex("女");
    //设置学生的外键,不高不设置,保存的学生将没有外键值
    s3.setCluss(c1);
    session.save(s1);
    session.save(s2);
    session.save(s3);
    c1.getStudents().add(s1);
    c1.getStudents().add(s3);
    c2.getStudents().add(s2);

    tx.commit(); //提交5个事务,保存数据
    } catch (Exception e) {
    e.printStackTrace();
    if(tx!=null)tx.rollback();
    }
    }
    //关联映射主要为查询服务 当具有多对一关系时,在获取多的一段的信息时可以直接获取一的一端的信息
    @Test
    public void testGet() {
    Student s1=(Student) session.get(Student.class, 1);
    System.out.println(s1.getName()+"-->"+s1.getCluss().getName());
    //获取班级信息
    System.out.println("================");
    Cluss c1=(Cluss) session.get(Cluss.class, 1);
    System.out.println(c1.getName()+"--->" +c1.getAddress());
    System.out.println("--------------");
    for (Student s : c1.getStudents()) {
    System.out.println(s.getName() + "--->" + s.getAge());
    }

    }

    }

关联映射之基于外键的单向一对一

  1. 身份证和人是一对一关系:
  • 表结构

  • 类结构
    • Person.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    package com.zhuchuli.vo;

    public class Person {
    private int id;
    private String name;
    private String sex;
    private Card card;
    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 getSex() {
    return sex;
    }
    public void setSex(String sex) {
    this.sex = sex;
    }
    public Card getCard() {
    return card;
    }
    public void setCard(Card card) {
    this.card = card;
    }

    }
  • Card.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.zhuchuli.vo;

public class Card {
private int id;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}

}
  • 映射文件
    • Card.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <hibernate-mapping package="com.zhuchuli.vo">

    <class name="Card" table="t_card">

    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <!-- property 指定属性的映射 -->
    <property name="address"></property>

    </class>
    </hibernate-mapping>
  • Person.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<hibernate-mapping package="com.zhuchuli.vo">

<class name="Person" table="t_person">

<id name="id" column="id">
<generator class="native"/>
</id>
<!-- property 指定属性的映射 -->
<property name="name"></property>
<property name="sex"></property>
<!-- 当多对一时,在多的一方外键不重复时,其实质就是一对一 -->
<many-to-one name="card" column="card_id" unique="true"></many-to-one>
</class>
</hibernate-mapping>
  • 测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    package com.zhuchuli.test;

    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.tool.hbm2ddl.SchemaExport;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;

    import com.zhuchuli.util.HibernateUtil;
    import com.zhuchuli.vo.Card;
    import com.zhuchuli.vo.Person;


    public class HibernateTest {
    private Session session=null;
    private Transaction tx=null;
    @Before
    public void setUp() {
    try {
    //获取Session对象
    session = HibernateUtil.getSession();
    //获取事务并且开启事务
    tx = session.beginTransaction();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    @After
    public void tear() {
    HibernateUtil.close();
    }
    /***
    * 将对象信息 转换为 关系信息
    */
    @Test
    public void testCreateDB() {
    Configuration cfg=new Configuration().configure();
    //使得hibernate映射信息转化为ddl(数据库定义语言)
    SchemaExport se = new SchemaExport(cfg);
    //第一参数:是否打印ddl语句
    //第二个参数:是否将ddl到数据库执行
    se.create(true, true);
    }
    /***
    * 一对多关联时保存数据会多出n挑更新语句,降低效率
    * 一般不会使用一对多来关联映射
    */
    @Test
    public void testInit() {
    try {
    Card c1=new Card();
    c1.setAddress("广东潮阳");
    Card c2=new Card();
    c2.setAddress("广东增城");

    Person p1=new Person();
    p1.setName("张三");
    p1.setSex("男");
    p1.setCard(c1);
    Person p2=new Person();
    p2.setName("李四");
    p2.setSex("男");
    p2.setCard(c2);

    session.save(c1);
    session.save(c2);
    session.save(p1);
    session.save(p2);
    tx.commit();
    } catch (Exception e) {
    if(tx!=null)tx.rollback();
    e.printStackTrace();
    }
    }
    //关联映射主要为查询服务 当具有多对一关系时,在获取多的一段的信息时可以直接获取一的一端的信息
    @Test
    public void testGet() {
    Person person=(Person) session.get(Person.class, 1);
    System.out.println(person.getName() + "\t" + person.getSex());
    System.out.println("----------------------------------------");
    System.out.println(person.getCard().getAddress());
    }

    }

关联映射基于外键之双向一对一

  1. 身份证和人是一对一关系:
  • 表结构

  • 类结构
    • Card.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package com.zhuchuli.vo;

    public class Card {
    private int id;
    private String address;
    private Person person;

    public Person getPerson() {
    return person;
    }
    public void setPerson(Person person) {
    this.person = person;
    }
    public int getId() {
    return id;
    }
    public void setId(int id) {
    this.id = id;
    }
    public String getAddress() {
    return address;
    }
    public void setAddress(String address) {
    this.address = address;
    }

    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.zhuchuli.vo;

public class Person {
private int id;
private String name;
private String sex;
private Card card;
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 getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}

}
  • 映射文件

    • Card.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <!-- package用于指定类所在的包,如果不指定,那么在指定class的name时,需要指定完全限定名 -->
    <hibernate-mapping package="com.zhuchuli.vo">

    <class name="Card" table="t_card">

    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <!-- property 指定属性的映射 -->
    <property name="address"></property>
    <!-- 一对一 -->
    <!-- name 指定的是当前类一对一的属性, property-ref指定的是另一类中的Card属性 -->
    <one-to-one name="person" property-ref="card"></one-to-one>
    </class>
    </hibernate-mapping>
  • Person.hbm.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <?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">
    <!-- package用于指定类所在的包,如果不指定,那么在指定class的name时,需要指定完全限定名 -->
    <hibernate-mapping package="com.zhuchuli.vo">

    <class name="Person" table="t_person">

    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <!-- property 指定属性的映射 -->
    <property name="name"></property>
    <property name="sex"></property>
    <!-- 当多对一时,在多的一方外键不重复时,其实质就是一对一 -->
    <many-to-one name="card" column="card_id" unique="true"></many-to-one>
    </class>
    </hibernate-mapping>
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package com.zhuchuli.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.zhuchuli.util.HibernateUtil;
import com.zhuchuli.vo.Card;
import com.zhuchuli.vo.Person;


public class HibernateTest {
private Session session=null;
private Transaction tx=null;
@Before
public void setUp() {
try {
//获取Session对象
session = HibernateUtil.getSession();
//获取事务并且开启事务
tx = session.beginTransaction();
} catch (Exception e) {
e.printStackTrace();
}
}
@After
public void tear() {
HibernateUtil.close();
}
/***
* 将对象信息 转换为 关系信息
*/
@Test
public void testCreateDB() {
Configuration cfg=new Configuration().configure();
//使得hibernate映射信息转化为ddl(数据库定义语言)
SchemaExport se = new SchemaExport(cfg);
//第一参数:是否打印ddl语句
//第二个参数:是否将ddl到数据库执行
se.create(true, true);
}
/***
* 一对多关联时保存数据会多出n挑更新语句,降低效率
* 一般不会使用一对多来关联映射
*/
@Test
public void testInit() {
try {
Card c1=new Card();
c1.setAddress("广东潮阳");
Card c2=new Card();
c2.setAddress("广东增城");

Person p1=new Person();
p1.setName("张三");
p1.setSex("男");
p1.setCard(c1);
Person p2=new Person();
p2.setName("李四");
p2.setSex("男");
p2.setCard(c2);

session.save(c1);
session.save(c2);
session.save(p1);
session.save(p2);
tx.commit();
} catch (Exception e) {
if(tx!=null)tx.rollback();
e.printStackTrace();
}
}
//关联映射主要为查询服务 当具有多对一关系时,在获取多的一段的信息时可以直接获取一的一端的信息
@Test
public void testGet() {
Person person=(Person) session.get(Person.class, 1);
System.out.println(person.getName() + "\t" + person.getSex());
System.out.println("----------------------------------------");
System.out.println(person.getCard().getPerson().getName());
}

}

关联映射之基于主键单向一对一

  1. 身份证和人之间的关系:
  • 表结构:

主键一对一.png

  • 类结构
    • Card.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    package com.zhuchuli.vo;

    public class Card {
    private String id;
    private String address;

    public String getId() {
    return id;
    }
    public void setId(String id) {
    this.id = id;
    }
    public String getAddress() {
    return address;
    }
    public void setAddress(String address) {
    this.address = address;
    }

    }
  • Person.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.zhuchuli.vo;

public class Person {
private String id;
private String name;
private String sex;
private Card card;

public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}

}
  • 映射文件
    • Card.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <hibernate-mapping package="com.zhuchuli.vo">

    <class name="Card" table="t_card">

    <id name="id" column="id">
    <generator class="assigned"/>
    </id>
    <!-- property 指定属性的映射 -->
    <property name="address"></property>

    </class>
    </hibernate-mapping>
  • Person.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<hibernate-mapping package="com.zhuchuli.vo">

<class name="Person" table="t_person">

<id name="id" column="id">
<generator class="foreign">
<param name="property">card</param>
</generator>
</id>
<!-- property 指定属性的映射 -->
<property name="name"></property>
<property name="sex"></property>
<!-- 基于主键的一对一 constrained="true"用于添加外键约束-->
<one-to-one name="card" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
  • 测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    package com.zhuchuli.test;

    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.tool.hbm2ddl.SchemaExport;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;

    import com.zhuchuli.util.HibernateUtil;
    import com.zhuchuli.vo.Card;
    import com.zhuchuli.vo.Person;


    public class HibernateTest {
    private Session session=null;
    private Transaction tx=null;
    @Before
    public void setUp() {
    try {
    //获取Session对象
    session = HibernateUtil.getSession();
    //获取事务并且开启事务
    tx = session.beginTransaction();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    @After
    public void tear() {
    HibernateUtil.close();
    }
    /***
    * 将对象信息 转换为 关系信息
    */
    @Test
    public void testCreateDB() {
    Configuration cfg=new Configuration().configure();
    //使得hibernate映射信息转化为ddl(数据库定义语言)
    SchemaExport se = new SchemaExport(cfg);
    //第一参数:是否打印ddl语句
    //第二个参数:是否将ddl到数据库执行
    se.create(true, true);
    }
    /***
    * 一对多关联时保存数据会多出n挑更新语句,降低效率
    * 一般不会使用一对多来关联映射
    */
    @Test
    public void testInit() {
    try {
    Card c1=new Card();
    c1.setId("1001");
    c1.setAddress("广东潮阳");
    Card c2=new Card();
    c2.setId("1002");
    c2.setAddress("广东增城");

    Person p1=new Person();
    p1.setName("张三");
    p1.setSex("男");
    p1.setCard(c1);
    Person p2=new Person();
    p2.setName("李四");
    p2.setSex("男");
    p2.setCard(c2);

    session.save(c1);
    session.save(c2);
    session.save(p1);
    session.save(p2);
    tx.commit();
    } catch (Exception e) {
    if(tx!=null)tx.rollback();
    e.printStackTrace();
    }
    }
    //关联映射主要为查询服务 当具有多对一关系时,在获取多的一段的信息时可以直接获取一的一端的信息
    @Test
    public void testGet() {
    Person person=(Person) session.get(Person.class, "1001");
    System.out.println(person.getName() + "\t" + person.getSex());
    System.out.println("----------------------------------------");
    System.out.println(person.getCard().getAddress());
    }

    }

关联映射之基于主键的双向一对一

  1. 身份证和人之间的关系:
  • 表结构:

主键双向一对一.png

  • 类结构
    • Card.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package com.zhuchuli.vo;

    public class Card {
    private String id;
    private String address;
    private Person person;
    public String getId() {
    return id;
    }
    public void setId(String id) {
    this.id = id;
    }
    public String getAddress() {
    return address;
    }
    public void setAddress(String address) {
    this.address = address;
    }
    public void setPerson(Person person){
    this.person=person;
    }
    public Person getPerson(){
    return person;
    }
    }
  • Person.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.zhuchuli.vo;

public class Person {
private String id;
private String name;
private String sex;
private Card card;

public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Card getCard() {
return card;
}
public void setCard(Card card) {
this.card = card;
}

}
  • 映射文件
    • Card.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <hibernate-mapping package="com.zhuchuli.vo">

    <class name="Card" table="t_card">

    <id name="id" column="id">
    <generator class="assigned"/>
    </id>
    <!-- property 指定属性的映射 -->
    <property name="address"></property>
    <one-to-one name="person"/>
    </class>
    </hibernate-mapping>
  • Person.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<hibernate-mapping package="com.zhuchuli.vo">

<class name="Person" table="t_person">

<id name="id" column="id">
<generator class="foreign">
<param name="property">card</param>
</generator>
</id>
<!-- property 指定属性的映射 -->
<property name="name"></property>
<property name="sex"></property>
<!-- 基于主键的一对一 constrained="true"用于添加外键约束-->
<one-to-one name="card" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
  • 测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    package com.zhuchuli.test;

    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.tool.hbm2ddl.SchemaExport;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;

    import com.zhuchuli.util.HibernateUtil;
    import com.zhuchuli.vo.Card;
    import com.zhuchuli.vo.Person;


    public class HibernateTest {
    private Session session=null;
    private Transaction tx=null;
    @Before
    public void setUp() {
    try {
    //获取Session对象
    session = HibernateUtil.getSession();
    //获取事务并且开启事务
    tx = session.beginTransaction();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    @After
    public void tear() {
    HibernateUtil.close();
    }
    /***
    * 将对象信息 转换为 关系信息
    */
    @Test
    public void testCreateDB() {
    Configuration cfg=new Configuration().configure();
    //使得hibernate映射信息转化为ddl(数据库定义语言)
    SchemaExport se = new SchemaExport(cfg);
    //第一参数:是否打印ddl语句
    //第二个参数:是否将ddl到数据库执行
    se.create(true, true);
    }
    /***
    * 一对多关联时保存数据会多出n挑更新语句,降低效率
    * 一般不会使用一对多来关联映射
    */
    @Test
    public void testInit() {
    try {
    Card c1=new Card();
    c1.setId("1001");
    c1.setAddress("广东潮阳");
    Card c2=new Card();
    c2.setId("1002");
    c2.setAddress("广东增城");

    Person p1=new Person();
    p1.setName("张三");
    p1.setSex("男");
    p1.setCard(c1);
    Person p2=new Person();
    p2.setName("李四");
    p2.setSex("男");
    p2.setCard(c2);

    session.save(c1);
    session.save(c2);
    session.save(p1);
    session.save(p2);
    tx.commit();
    } catch (Exception e) {
    if(tx!=null)tx.rollback();
    e.printStackTrace();
    }
    }
    //关联映射主要为查询服务 当具有多对一关系时,在获取多的一段的信息时可以直接获取一的一端的信息
    @Test
    public void testGet() {
    Person person=(Person) session.get(Person.class, "1001");
    System.out.println(person.getName() + "\t" + person.getSex());
    System.out.println("----------------------------------------");
    System.out.println(person.getCard().getAddress());
    System.out.println("==========================");
    Card card=(Card)session.get(Card.class,"1001");
    System.out.println(card.getAddress());
    System.out.println("---------------------");
    System.out.println(card.getPerson().getName()+"\t"+card.getPerson().getSex);

    }

    }

关联映射之基于主键的单向多对多

  1. 角色和权限之间的关系是多对多
  • 表结构

单向多对多.png

  • 类结构
    • Role.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class Role implements Serializable{
    private int id;
    private String name;
    private Set<Permission> permissions=new HashSet<Permission>();
    public Set<Permission> getPermissions() {
    return permissions;
    }
    public void setPermissions(Set<Permission> permissions) {
    this.permissions = permissions;
    }
    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;
    }

    }
  • permission.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Permission implements Serializable{
private int id;
private String name;
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;
}
}
  • 映射文件
    • Permission.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <hibernate-mapping package="com.zhuchuli.vo">

    <class name="Permission" table="t_permission">

    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <!-- property 指定属性的映射 -->
    <property name="name"></property>

    </class>
    </hibernate-mapping>
  • Role.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<hibernate-mapping package="com.zhuchuli.vo">

<class name="Role" table="t_role">

<id name="id" column="id">
<generator class="native"/>
</id>
<!-- property 指定属性的映射 -->
<property name="name"></property>
<!-- table为连接表的名称 -->
<set name="permissions" table="t_role_permission">
<!-- key指明当前类在关联表中的外键 -->
<key column="rid"></key>
<!-- column为多对多的另一方在关联表中的外键 -->
<many-to-many column="pid" class="Permission"></many-to-many>
</set>
</class>
</hibernate-mapping>
  • 测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    public class HibernateTest {
    private Session session=null;
    private Transaction tx=null;
    @Before
    public void setUp() {
    try {
    //获取Session对象
    session = HibernateUtil.getSession();
    //获取事务并且开启事务
    tx = session.beginTransaction();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    @After
    public void tear() {
    HibernateUtil.close();
    }
    /***
    * 将对象信息 转换为 关系信息
    */
    @Test
    public void testCreateDB() {
    Configuration cfg=new Configuration().configure();
    //使得hibernate映射信息转化为ddl(数据库定义语言)
    SchemaExport se = new SchemaExport(cfg);
    //第一参数:是否打印ddl语句
    //第二个参数:是否将ddl到数据库执行
    se.create(true, true);
    }
    /***
    * 一对多关联时保存数据会多出n挑更新语句,降低效率
    * 一般不会使用一对多来关联映射
    */
    @Test
    public void testInit() {
    try {
    Role r1=new Role();
    r1.setName("普通用户");
    Role r2=new Role();
    r2.setName("会员");

    Permission p1=new Permission();
    p1.setName("用户查看");
    Permission p2=new Permission();
    p2.setName("用户添加");
    Permission p3=new Permission();
    p3.setName("用户修改");
    Permission p4=new Permission();
    p4.setName("用户删除");

    session.save(p1);
    session.save(p2);
    session.save(p3);
    session.save(p4);

    r1.getPermissions().add(p1);
    r1.getPermissions().add(p2);
    r2.getPermissions().add(p1);
    r2.getPermissions().add(p2);
    r2.getPermissions().add(p3);
    r2.getPermissions().add(p4);
    session.save(r1);
    session.save(r2);
    tx.commit();
    } catch (Exception e) {
    if(tx!=null)tx.rollback();
    e.printStackTrace();
    }
    }
    //多对多测试
    @Test
    public void testGet() {
    Role r=(Role)session.get(Role.class, 2);
    System.out.println(r.getName());
    System.out.println("--------------------------");
    for (Permission p : r.getPermissions()) {
    System.out.println(p.getName());
    }
    }

    }

关联映射之基于主键的双向多对多

  1. 角色和权限之间的关系是多对多
  • 表结构

双向多对多.png

  • Role.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Role implements Serializable{
private int id;
private String name;
private Set<Permission> permissions=new HashSet<Permission>();
public Set<Permission> getPermissions() {
return permissions;
}
public void setPermissions(Set<Permission> permissions) {
this.permissions = permissions;
}
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;
}

}
  • permission.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Permission implements Serializable{
private int id;
private String name;
private Set<Role> roles=new HashSet<Role>();

public Set<Role> getRoles() {
return roles;
}
public void setRoles(Set<Role> roles) {
this.roles = roles;
}
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;
}
}
  • 映射文件
    • Permission.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <hibernate-mapping package="com.zhuchuli.vo">

    <class name="Permission" table="t_permission">

    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <!-- property 指定属性的映射 -->
    <property name="name"></property>
    <set name="roles" table="t_role_permission" inverse="true">
    <key column="pid"></key>
    <many-to-many column="rid" class="Role"></many-to-many>
    </set>
    </class>
    </hibernate-mapping>
  • Role.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<hibernate-mapping package="com.zhuchuli.vo">

<class name="Role" table="t_role">

<id name="id" column="id">
<generator class="native"/>
</id>
<!-- property 指定属性的映射 -->
<property name="name"></property>
<!-- table为连接表的名称 -->
<set name="permissions" table="t_role_permission">
<!-- key指明当前类在关联表中的外键 -->
<key column="rid"></key>
<!-- column为多对多的另一方在关联表中的外键 -->
<many-to-many column="pid" class="Permission"></many-to-many>
</set>
</class>
</hibernate-mapping>
  • 测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class HibernateTest {

    //多对多测试
    @Test
    public void testGet() {
    Role r=(Role)session.get(Role.class, 2);
    System.out.println(r.getName());
    System.out.println("--------------------------");
    for (Permission p : r.getPermissions()) {
    System.out.println(p.getName());
    }
    System.out.println("=====================");
    Permission p=(Permission)session.get(Permission.class,2);
    System.out.println(p.getName());
    System.out.println("-------------------------");
    for (Role r2 : p.getRoles()) {
    System.out.println(r2.getName());
    }
    }

    }

关联映射之组件映射 (一个表多个类)

  1. 如果一个员工有多个联系方式的情况下,可以将联系方式单独提出一个类来进行管理。
  • 表结构

组件.png

  • 类结构
    • Links.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class Links {
    private String qq;
    private String email;
    private String phone;
    public String getQq() {
    return qq;
    }
    public void setQq(String qq) {
    this.qq = qq;
    }
    public String getEmail() {
    return email;
    }
    public void setEmail(String email) {
    this.email = email;
    }
    public String getPhone() {
    return phone;
    }
    public void setPhone(String phone) {
    this.phone = phone;
    }

    }
  • Employee.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class Employee {
private int id;
private String name;
private int age;
private Links link;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Links getLink() {
return link;
}
public void setLink(Links link) {
this.link = link;
}

}
  • 映射文件

    • Employee.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <!-- package用于指定类所在的包,如果不指定,那么在指定class的name时,需要指定完全限定名 -->
    <hibernate-mapping package="com.zhuchuli.vo">

    <class name="Employee" table="t_employee">

    <id name="id" column="id">
    <generator class="native"/>
    </id>
    <!-- property 指定属性的映射 -->
    <property name="name"></property>
    <property name="age"></property>
    <component name="link" class="Links">
    <property name="email"></property>
    <property name="qq"></property>
    <property name="phone"></property>
    </component>

    </class>
    </hibernate-mapping>
  • 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    public class HibernateTest {
    private Session session=null;
    private Transaction tx=null;
    @Before
    public void setUp() {
    try {
    //获取Session对象
    session = HibernateUtil.getSession();
    //获取事务并且开启事务
    tx = session.beginTransaction();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    @After
    public void tear() {
    HibernateUtil.close();
    }
    /***
    * 将对象信息 转换为 关系信息
    */
    @Test
    public void testCreateDB() {
    Configuration cfg=new Configuration().configure();
    //使得hibernate映射信息转化为ddl(数据库定义语言)
    SchemaExport se = new SchemaExport(cfg);
    //第一参数:是否打印ddl语句
    //第二个参数:是否将ddl到数据库执行
    se.create(true, true);
    }
    /***
    * 一对多关联时保存数据会多出n挑更新语句,降低效率
    * 一般不会使用一对多来关联映射
    */
    @Test
    public void testInit() {
    try {
    Links link=new Links();
    link.setEmail("dshaui@qq.com");
    link.setPhone("4241564361");
    link.setQq("535313123");
    Employee e1=new Employee();
    e1.setName("张三丰");
    e1.setAge(125);
    e1.setLink(link);
    session.save(e1);
    tx.commit();
    } catch (Exception e) {
    if(tx!=null)tx.rollback();
    e.printStackTrace();
    }
    }
    //关联映射主要为查询服务 当具有多对一关系时,在获取多的一段的信息时可以直接获取一的一端的信息
    @Test
    public void testGet() {
    Employee e=(Employee)session.get(Employee.class, 1);
    System.out.println(e.getName()+"\t"+e.getAge());
    System.out.println("----------------");
    System.out.println(e.getLink().getEmail());
    System.out.println(e.getLink().getQq());
    System.out.println(e.getLink().getPhone());
    }

    }

OpenSessionInView

组合主键

  1. 学生管理系统中,成绩表的主键组合主键。
  • 表结构

组合主键.PNG

  • 组合主键在Hibernate中类的结构有3种
    • 类结构1:Result.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class Result implements Serializable{
    private int stuId;
    private int subId;
    private double score;
    public int getStuId() {
    return stuId;
    }
    public void setStuId(int stuId) {
    this.stuId = stuId;
    }
    public int getSubId() {
    return subId;
    }
    public void setSubId(int subId) {
    this.subId = subId;
    }
    public double getScore() {
    return score;
    }
    public void setScore(double score) {
    this.score = score;
    }

    }
  • 类的结构2 ResultPK.java、Result.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ResultPK implements Serializable {
private int stuId;
private int subId;
public int getStuId() {
return stuId;
}
public void setStuId(int stuId) {
this.stuId = stuId;
}
public int getSubId() {
return subId;
}
public void setSubId(int subId) {
this.subId = subId;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

/***
* 如果组合主键的字段是类的属性时,该类必须实现Serializable
* @author 1huangzewei
*
*/
public class Result implements Serializable{

private double score;
private ResultPK id;

public ResultPK getId() {
return id;
}
public void setId(ResultPK id) {
this.id = id;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}

}
  • 类的结构3
    • Student、Subject是一个单独的类,需要把它们配置成Result的成员变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.zhuchuli.vo;

public class Student {
private int id;
private String name;
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;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/***
* 如果组合主键的字段是类的属性时,该类必须实现Serializable
* @author 1huangzewei
*
*/
public class Result implements Serializable{
private Student student;
private Subject subject;
private double score;

public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.zhuchuli.vo;

public class Subject {
private int id;
private String name;
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;
}

}
  • 映射文件
    • 类结构1 相匹配的映射文件: Result.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <hibernate-mapping package="com.zhuchuli.vo">
    <class name="Result" table="t_result">

    <!-- 组合主键映射 -->
    <composite-id>
    <key-property name="stuId"></key-property>
    <key-property name="subId"></key-property>
    </composite-id>
    <!-- property 指定属性的映射 -->
    <property name="score"></property>
    </class>
    </hibernate-mapping>
  • 类结构2 相匹配的映射文件: Result.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
<hibernate-mapping package="com.zhuchuli.vo">
<class name="Result" table="t_result">

<!-- 组合主键映射 -->
<composite-id name="id" class="ResultPK">
<key-property name="stuId"></key-property>
<key-property name="subId"></key-property>
</composite-id>
<!-- property 指定属性的映射 -->
<property name="score"></property>
</class>
</hibernate-mapping>
  • 类结构3 相匹配的映射文件: Result.hbm.xml、Student.hbml.xml、Subject.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- package用于指定类所在的包,如果不指定,那么在指定class的name时,需要指定完全限定名 -->
<hibernate-mapping package="com.zhuchuli.vo">
<class name="Result" table="t_result">

<!-- 组合主键映射 -->
<composite-id>
<key-many-to-one name="student" column="stuId"></key-many-to-one>
<key-many-to-one name="subject" column="subId"></key-many-to-one>
</composite-id>
<!-- property 指定属性的映射 -->
<property name="score"></property>
</class>
</hibernate-mapping>
1
2
3
4
5
6
7
8
<hibernate-mapping package="com.zhuchuli.vo">
<class name="Student" table="t_student">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
</class>
</hibernate-mapping>
1
2
3
4
5
6
7
8
9
<!-- package用于指定类所在的包,如果不指定,那么在指定class的name时,需要指定完全限定名 -->
<hibernate-mapping package="com.zhuchuli.vo">
<class name="Subject" table="t_subject">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
</class>
</hibernate-mapping>
  • 测试
    • 类结构1、类结构2、类结构3测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    public class HibernateTest {
    private Session session=null;
    private Transaction tx=null;
    @Before
    public void setUp() {
    try {
    //获取Session对象
    session = HibernateUtil.getSession();
    //获取事务并且开启事务
    tx = session.beginTransaction();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    @After
    public void tear() {
    HibernateUtil.close();
    }
    /***
    * 将对象信息 转换为 关系信息
    */
    @Test
    public void testCreateDB() {
    Configuration cfg=new Configuration().configure();
    //使得hibernate映射信息转化为ddl(数据库定义语言)
    SchemaExport se = new SchemaExport(cfg);
    //第一参数:是否打印ddl语句
    //第二个参数:是否将ddl到数据库执行
    se.create(true, true);
    }
    @Test
    public void testInit() {
    try {
    Result r=new Result();
    r.setStuId(1);
    r.setSubId(1);
    r.setScore(70);
    session.save(r);
    tx.commit();
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    if(tx!=null)tx.rollback();
    }
    }
    @Test
    public void testGet() {
    Result r=new Result();
    r.setStuId(1);
    r.setSubId(1);
    Result r1=(Result) session.get(Result.class,r);
    System.out.println(r1.getScore());
    }

    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class HibernateTest {
private Session session=null;
private Transaction tx=null;
@Before
public void setUp() {
try {
//获取Session对象
session = HibernateUtil.getSession();
//获取事务并且开启事务
tx = session.beginTransaction();
} catch (Exception e) {
e.printStackTrace();
}
}
@After
public void tear() {
HibernateUtil.close();
}
/***
* 将对象信息 转换为 关系信息
*/
@Test
public void testCreateDB() {
Configuration cfg=new Configuration().configure();
//使得hibernate映射信息转化为ddl(数据库定义语言)
SchemaExport se = new SchemaExport(cfg);
//第一参数:是否打印ddl语句
//第二个参数:是否将ddl到数据库执行
se.create(true, true);
}
@Test
public void testInit() {
try {
ResultPK pk=new ResultPK();
pk.setStuId(1);
pk.setSubId(1);
Result r=new Result();
r.setId(pk);
r.setScore(70);
session.save(r);
tx.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
if(tx!=null)tx.rollback();
}
}
@Test
public void testGet() {
ResultPK pk=new ResultPK();
pk.setStuId(1);
pk.setSubId(1);
Result r1=(Result) session.get(Result.class,pk);
System.out.println(r1.getScore());
}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class HibernateTest {
private Session session=null;
private Transaction tx=null;
@Before
public void setUp() {
try {
//获取Session对象
session = HibernateUtil.getSession();
//获取事务并且开启事务
tx = session.beginTransaction();
} catch (Exception e) {
e.printStackTrace();
}
}
@After
public void tear() {
HibernateUtil.close();
}
/***
* 将对象信息 转换为 关系信息
*/
@Test
public void testCreateDB() {
Configuration cfg=new Configuration().configure();
//使得hibernate映射信息转化为ddl(数据库定义语言)
SchemaExport se = new SchemaExport(cfg);
//第一参数:是否打印ddl语句
//第二个参数:是否将ddl到数据库执行
se.create(true, true);
}
@Test
public void testInit() {
try {
Student student=(Student) session.get(Student.class, 1);
Subject subject=(Subject) session.get(Subject.class, 1);
Result result=new Result();
result.setStudent(student);
result.setSubject(subject);
result.setScore(80);
session.save(result);
tx.commit();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
if(tx!=null)tx.rollback();
}
}
@Test
public void testGet() {
Student student=(Student) session.get(Student.class, 1);
Subject subject=(Subject) session.get(Subject.class, 1);
Result result=new Result();
result.setStudent(student);
result.setSubject(subject);
Result r1=(Result) session.get(Result.class,result);
System.out.println(r1.getScore());
}

}

有序集合映射(List)

  • 有序集合映射 表结构
  • indx为有序值:idx

list.PNG

  • 类结构
    • Cluss.java
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class Cluss implements Serializable{
    private int id;
    private String name;
    private String address;
    private List<Student> students=new ArrayList<Student>();
    public int getId() {
    return id;
    }
    public List<Student> getStudents() {
    return students;
    }
    public void setStudents(List<Student> students) {
    this.students = students;
    }
    public void setId(int id) {
    this.id = id;
    }
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public String getAddress() {
    return address;
    }
    public void setAddress(String address) {
    this.address = address;
    }

    }
  • Student.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Student implements Serializable{
private int id;
private String name;
private int age;
private String sex;

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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}

}
  • 映射文件
    • Cluss.hbm.xml
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <hibernate-mapping package="com.zhuchuli.vo">

    <class name="Cluss" table="t_class">
    <id name="id">
    <generator class="native"></generator>
    </id>
    <property name="name"></property>
    <property name="address"></property>
    <list name="students">
    <key column="cluss_id"></key>
    <!-- 有序列 顺序有hibernate来维护 -->
    <list-index base="1" column="idx"></list-index>
    <one-to-many class="Student"/>
    </list>

    </class>
    </hibernate-mapping>
  • Student.hbm.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- package用于指定类所在的包,如果不指定,那么在指定class的name时,需要指定完全限定名 -->
<hibernate-mapping package="com.zhuchuli.vo">
<class name="Student" table="t_student" schema="">
<id name="id">
<generator class="native"/>
</id>
<!-- property 指定属性的映射 -->
<property name="name"/>
<property name="age" />
<property name="sex" />


</class>
</hibernate-mapping>
  • 测试
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    public class HibernateTest {
    private Session session=null;
    private Transaction tx=null;
    @Before
    public void setUp() {
    try {
    //获取Session对象
    session = HibernateUtil.getSession();
    //获取事务并且开启事务
    tx = session.beginTransaction();
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    @After
    public void tear() {
    HibernateUtil.close();
    }
    /***
    * 将对象信息 转换为 关系信息
    */
    @Test
    public void testCreateDB() {
    Configuration cfg=new Configuration().configure();
    //使得hibernate映射信息转化为ddl(数据库定义语言)
    SchemaExport se = new SchemaExport(cfg);
    //第一参数:是否打印ddl语句
    //第二个参数:是否将ddl到数据库执行
    se.create(true, true);
    }
    @Test
    public void testInit() {
    try {
    Student s1=new Student();
    s1.setName("张三");
    s1.setAge(23);
    s1.setSex("男");
    Student s2=new Student();
    s2.setName("李四");
    s2.setAge(21);
    s2.setSex("男");
    Student s3=new Student();
    s3.setName("王小蒙");
    s3.setAge(20);
    s3.setSex("女");
    session.save(s1);
    session.save(s2);
    session.save(s3);
    Cluss c1=new Cluss();
    c1.setName("D-201");
    c1.setAddress("d-201");
    Cluss c2=new Cluss();
    c2.setName("C-201");
    c2.setAddress("c-201");
    c1.getStudents().add(s1);
    c1.getStudents().add(s3);
    c2.getStudents().add(s2);
    session.save(c1);
    session.save(c2);
    tx.commit();
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    if(tx!=null)tx.rollback();
    }
    }
    @Test
    public void testGet() {
    Cluss c1=(Cluss) session.get(Cluss.class,1);
    System.out.println(c1.getName() + "\t" +c1.getAddress());
    System.out.println("------------------------------");
    for (Student s : c1.getStudents()) {
    System.out.println(s.getName() + "\t" + s.getSex() + "\t" + s.getAge());
    }
    }
    }

cascade 和 inverse

  1. cascade 级联:操作一个对象时,可以附带操作关联对象
    1
    <many-to-one name="card" column="card_id"  cascade="save-update"></many-to-one>
  • 在many-to-one中 将级联设置为save-update,意味着在保存多的一端数据时,会检查关联对象,如果关联对象没有保存或更新,那么级联会将关联对象保存和更新.如果cascase值为delete,那么会级联将关联对象删除,如果有多个记录关联同一个级联对象时会报错,不建议设置为delete,如果值为all,所有相关动作都会级联,建议在many-to-one时设置save-update.
1
2
3
4
<set name="students"  cascade="save-update"> 
<key column="cluss_id"></key>
<one-to-many class="Student"/>
</set>
  • 在one-to-many中,如果cascase是save-update,会级联保存多的一端数据,前提要在一的一端设置关联对象,但是会多出n条update语句,所以不建议在一的一端设置为save-update,如果cascase值为delete,会级联会删除多的一端的数据。一般情况下不会设置delete,在企业中,删除大多数为虚拟删除。
  1. invers:反e转,表示控制关系(外健)由谁来管理。多的一方默认是管理(外健)的,一的一方默认也是管理关系的。但是一的一方可以设置inverse=true,让另一方来控制关系,有一的一方控制关系,那么在管理关系会发出update语句。invserse控制是谁来管理关系。cascade控制如何级联操作。

hql

  1. HQL:hibernate query language:hibernate的查询语句,是一种完全面向对象的查询语言。编写Hql语句 和 sql几乎相同 ,关键字都一样,不区分大小写,hql查询的是类,不是表,字段写属性名,而不是表中字段名

Criteria查询

  1. 完全面向对象查询

本地sql

  1. Hibernate支持跨数据平台,导致一些数据库特有的功能Hibernate不支持。所以Hibernate提供了解决方法,那就是使用本地sql进行查询 –hibernate支持使用sql进行。

过滤器

  1. 过滤器:处理具有“显性(visibility)”规则的数据
  2. 使用Hibernate filter。 Hibernate filter是全局有效的、具有名字、可以带参数的过滤器, 对于某个特定的Hibernate session您可以选择是否启用(或禁用)某个过滤器。
  3. 使用步骤
    • 定义过滤器
    1
    2
    3
    4
    5
    <!-- 过滤器的定义 name是过滤器的名称 全局唯一 -->
    <filter-def name="userFilter">
    <!-- 过滤器可以携带参数,需要指定参数的名称和类型 -->
    <filter-param name="age" type="int"/>
    </filter-def>
  • 在类的映射文件中引用过滤器
1
2
<!-- 引用过滤器时 需要指定名称和条件 -->
<filter name="userFilter" condition="age>:age"></filter>
  • 在类中的应用
1
2
3
4
5
6
7
8
9
10
11
/***
* 过滤器的使用
*/
@Test
public void testFilter() {
session.enableFilter("userFilter").setParameter("age",20);
List<User> users=session.createQuery("from User").list();
for (User user : users) {
System.out.println(user.getName() + "\t" + user.getAge());
}
}

加载策略和抓取策略

  1. 加载策略指hibernate如何查询数据,加载策略有两种方式:一种是即时架加载,一种是延迟加载。

  2. 即时加载策略是指调用方法立即到数据库查询。

  3. get方法:是属于即时加载策略

    1
    2
    3
    4
    5
    6
    7
    8
    /**
    * get()是属于及时加载,获取数据时,如果不存在返回null
    */
    @Test
    public void testGet() {
    User user=(User)session.get(User.class, 1);
    System.out.println(user.getName());
    }
  4. List()方法也属性即时加载策略

    1
    2
    3
    4
    5
    6
    7
    8
    9
    /**
    * 测试List:该方法也是及时加载
    */
    @Test
    public void testList() {
    List<User> users=session.createQuery("from User").list();
    System.out.println("----------------");
    System.out.println(users.size());
    }
  • 即时记载在需要立即使用数据时使用。— 响应速度比较快。
  1. 延迟加载又称为懒加载 —> 懒加载可以提供系统使用率,在调用方法时不会立即到数据库查询数据,只有真正使用到数据时才去数据库查询。
1
2
3
4
5
6
7
8
9
10
11
/***
* load:延迟加载或懒加载
*/
@Test
public void testLoad() {
//load方法查询数据 如果数据不存在将会抛出异常
User user=(User)session.load(User.class, 1);
System.out.println(user.getId());
System.out.println("------------");
System.out.println(user.getName());//到数据库查询
}
  1. 懒加载:在关联查询中也可以使用懒加载;
    • Many-to-one:
    1
    <many-to-one name="cluss" column="cluss_id"  lazy="proxy"></many-to-one>
  • Lazy的值默认是proxy,是懒加载模式
  • no-proxy:也是懒加载模式,只是加载对象不使用代理。
  • lazy=”false”时采用即时加载。
  • set
1
2
3
4
<set name="students" lazy="true">
<key column="cluss_id"></key>
<one-to-many class="Student"/>
</set>
  • lazy=”true”默认,采用懒加载
  • Lazy=”false”:采用即时加载,一次将关联对象查询出来。
  • Lazy=”extra”:聪明的懒加载模式,如果只是查询关联对象的大小时,只会查询个数,不会查询数据。
  • Class:查询对象默认是lazy=true
  • property默认是lazy=false
  1. 抓取策略:指查询数据时,采用什么样的sql语句来查询。
    1
    <many-to-one name="cluss" column="cluss_id"  lazy="proxy" fetch="select"></many-to-one>
  • Select采用的是select语句查询数据,默认采用select,在这种抓取策略下lazy才有意义。
  • Join抓取,采用的额join语句查询数据,一次将关联数据查出,lazy没有意义了。

一级缓存、二级缓存和查询缓存

  1. 缓存:提高执行效率。
  2. hibernate提供了3类缓存:一级缓存,二级缓存,查询缓存。
  3. 一级缓存又称为session缓存,是线程级别的缓存。生命周期比较短。
    • get()方法获取,先检查缓存中是否有该数据,如果有直接使用,如果没有那么从数据库中查询,并写入缓存。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /**
    * get()属于一级缓存
    */
    @Test
    public void testGet() {
    User user=(User)session.get(User.class, 1);
    System.out.println(user.getName());
    System.out.println("---------------");
    user=(User)session.get(User.class, 1);
    System.out.println(user.getName());
    }
  • load()方法获取数据,先检查缓存中是否有该数据,如果有直接使用,如果没有那么从数据库中查询,并写入缓存。
1
2
3
4
5
6
7
8
9
10
11
/**
* load()也属于一级缓存
*/
@Test
public void testLoads() {
User user=(User)session.load(User.class, 1);
System.out.println(user.getName());
System.out.println("---------------");
user=(User)session.load(User.class, 1);
System.out.println(user.getName());
}
  • List()方法,直接从数据库中获取,获取后将数据存入到缓存中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* load()也属于一级缓存
*/
@Test
public void testList() {
List<User> users=session.createQuery("from User").list();
System.out.println("----------------");
User user=(User)session.load(User.class, 1);
System.out.println(user.getName());
System.out.println("----------------");
users=session.createQuery("from User").list();

System.out.println(users.size());
}
  • iterate()方法,属于懒加载模式,先获取数据的id,如果使用数据再根据id查询数据,是一种延迟加载方式。Iterate方法获取数据时会先插件缓存,如果有直接使用,如果没有再去数据库查询,然后再把查询结果写入到缓存中。
  • 1 和 N+1 问题:1是指list方法通过一条sql语句将所有的数据查询出来,而iterate方法通过n+1条sql语句将数据查询。他们的不同在于加载数据的方式不同。
  • 缓存的管理:一般情况下不用管理一级缓存,如果在进行批量处理时需要管理缓存。清理缓存可以使用:evict清除指定对象,clear清空缓存,flush刷新缓存数据,close关闭缓存。
  1. 二级缓存又称为SessionFactory缓存,是进程级别的,生命周期比较长,并且可以在集群中使用。缓存的数据比较多,当需要清理缓存使用相关算法进行清理。比如:LRU和FIFO等。Hibernate二级缓存采用第三方插件来实现。
  2. 二级缓存使用步骤:
    • 新建项目
    • 导入jar包
    • 添加ehcache.xml配置文件到src下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!-- 
    maxElementsInMemory:最多缓存元素的个数
    eternal:是否永久缓存
    timeToIdleSeconds 空闲时间
    timeToLiveSeconds 存活时间
    overflowToDisk 是否溢出到磁盘
    -->
    <defaultCache
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="120"
    timeToLiveSeconds="120"
    overflowToDisk="true"
    />
  • 在hibernate.cfg.xml开启二级缓存
1
2
3
4
<!-- 开启二级缓存 -->
<property name="cache.use_second_level_cache">true</property>
<property name="cache.provider_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
  • 在映射文件中添加<cache/>标签
1
2
3
<class name="User" table="t_user" schema="">
<cache usage="read-only"/>
</class>
  • 测试:使用二级缓存时,说明在关闭session时还能继续查到数据。
1
2
3
4
5
6
7
8
9
10
11
12
/**
* get()是属于及时加载,获取数据时,如果不存在返回null
*/
@Test
public void testGet() {
User user=(User)session.get(User.class, 1);
System.out.println(user.getName());
System.out.println("---------------");
session=HibernateUtil.getSession();
user=(User)session.get(User.class, 1);
System.out.println(user.getName());
}
  1. 查询缓存:在二级缓存的基础上使用,
    • 开启查询缓存 hibernate.cfg.xml
    1
    2
    <!-- 开启查询缓存 -->
    <property name="cache.use_query_cache">true</property>
  • 在查询数据时,设置查询缓存有效 setCacheable(true)
1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
public void testList() {
List<User> users=session.createQuery("from User")
.setCacheable(true)
.list();
System.out.println("----------------");
User user=(User)session.load(User.class, 1);
System.out.println(user.getName());
System.out.println("----------------");
users=session.createQuery("from User").setCacheable(true).list();

System.out.println(users.size());
}

事务隔离级别

  1. 从低到高: 读取未提交,读取已提交,可重复读,序列化
  2. 我们一般采用读取已提交,配合各种并发访问控制策略来达到事务控制的目的。

锁机制

  1. 乐观锁和悲观锁

Hibernate中文学习文档 http://docs.jboss.org/hibernate/core/3.5/reference/zh-CN/html_single/#mapping-declaration-id