【开源框架 - Hibernate】基础知识

准备+前言

Maven + Eclipse Luna + Tomcat 7 + MySQL 5.7.10

Hibernate 版本

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-core</artifactId>
  <version>3.6.10.Final</version>
</dependency>

注:

还需要导入 javassist 的包、MySQL 数据驱动包,不然运行不了

<!-- https://mvnrepository.com/artifact/javassist/javassist -->
<dependency>
  <groupId>javassist</groupId>
  <artifactId>javassist</artifactId>
  <version>3.12.1.GA</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.38</version>
</dependency>

名词解释

SQL 语言包括三种主要程序设计语言类别的语句:数据定义语言(DDL)、数据操作语言(DML)及数据控制语言(DCL)

DDL(数据定义语言):Data Definition Language

指的是定义数据格式(数据库结构、表结构)的语句:如创建数据库、创建表、修改表哈

DML(数据操作语言):Data Manipulation Language

指的是操作表中数据,插入、删除、修改、排序、检索

DCL(数据控制语言)

指的是用来设置或者更改数据库用户或角色权限的语句:如 GRANT、DENY、REVOKE 等语句s

Hibernate 旅程

这里描述 Hibernate 里重要的知识点,概要

映射配置基础

项目中有一个主配置文件,多个实体映射配置文件,在主配置文件中导入实体映射文件,实体映射文件一般置于和实体同一包内,以便于修改(当项目是 maven 管理时除外)。

1. 主配置文件(hibernate.cfg.xml)

主配置文件内容按作用可分为三类:

  • 数据库信息:方言、JdbcUrl、驱动、用户名、密码

    <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="hibernate.connection.url">jdbc:mysql:///hibernate_test</property>
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password">123456</property>
  • 导入映射文件:实体类与表之间的映射配置

    <mapping resource="Person.hbm.xml"/>
  • 其他配置:sql 语句、自动建表等

    <property name="hibernate.show_sql">true</property>
    <property name="hibernate.format_sql">false</property>
    <property name="hbm2ddl.auto">update</property>

其他注意事项

  1. 配置的 key 前面的 hibernate. 前缀 可以有,也可以没有。如 hibernate.dialect 或 dialect 都可以。
  2. 自动建表说明:

create:先删除,再创建
update:如果表不存在就创建,不一样就更新,一样就什么都不做。
create-drop:初始化时创建表,SessionFactory 执行 close() 时删除表。
validate:验证表结构是否一致,如果不一致,就抛异常。

2. 实体映射文件(Object.hbm.xml)

2.1. 普通属性映射配置

property 节点用于映射数据库中的基本属性,字符串、数字、日期等,属性如下描述:

<class name="Person" table="person">
  <property name="name" type="string" column="name" length="20"/>
  <property name="age" type="int" column="age" not-null="true"/>
  <property name="birthDay" type="date" column="birthDay"/>
</class>
  • name:对象中的属性名
  • type:类型,不写时,Hibernate 会自动检测;两种写法:Java 中类全名、Hibernate 规定的类型
  • column:对应数据库表中的列名,默认为属性名
  • length:长度,有些类型是没有长度的 int、date,默认为 255
  • not-null:非空约束,默认为 false

2.2 主键映射配置

id 节点用于映射主键,generator 子节点用于指定主键生成策略,几种生成策略如下:

<class name="Person" table="person">
  <id name="id" type="int" column="id">
    <generator class="native" />
  </id>
</class>
  • identity:使用数据库主键生成策略(oracle 不支持,MS SQL Server、MySQL 自动增长)
  • sequence:在 DB2,PostgreSQL,Oracle,SAP DB,McKoi 中使用序列(sequence)
  • hilo:高低位算法生成策略,需要额外的建表
  • native:根据底层数据库的能力选择 identity、sequence 或者 hilo 中的一个。
  • assigned:手工指定主键值
  • uuid:自动生成 uuidforeign:外键生成策略
  • increment:先查询当前最大值,再 +1,由 Hibernate 维护(和由数据库维护的 identity 区别开),并不是数据库维护,具有线程安全问题,不推荐使用

其他注意事项:

  • 在定义列名时,千万要留意字段名字是否和数据库的保留字段重合(如:desc )
  • 除 name 以外其他的属性都是可以省略的
  • Java 类型和 Hibernate 中的类型对应需要查文档,一般都是 Java 类型首字母小写,具体见 表 1:Java 类型与 Hibernate类型映射表
  • Date 类型常用的分为三种:date、time、timestamp ,具体见 表 2:Hibernate时间类型表

映射配置进阶

1. 集合映射配置(值类型)

Set:HashSet 无序,不重复,可再进行排序

# Person.java
private Set<String> address;
# Person.hbm.xml
<set name="address" table="person_address" 
     sort="unsorted|natural|comparatorClass">
  <key column="personId"></key>
  <element type="string" column="address" ></element>
</set>

name:类中属性名
sort:unsorted|natural|comparatorClass 三者选一,默认为unsorted(内存中排序)
order-by:指 order by 子句,是 SQL 语句,是操作的集合表(数据库中排序)
table:集合表的名称
key-column:集合外键的列名
element-type:集合中元素的类型
element-column:集合元素的列名

注: 当需要对 Set 进行内存中排序时(sort 属性),注入的实现类必须是可排序的,如:TreeSet、LinkHashSet

List:有序,可重复,不可再进行排序,因为本身就有序

# Person.java
private List<String> addressList;
# Person.hbm.xml
<list name="addressList" table="person_address_list">
  <key column="personId"/>
  <list-index column="idx"/>
  <element type="string" column="address"/>
</list>

Map:键值对 HashMap 无序,不重复(以 key 为准),可以再进行排序

# Person.java
private Map<String, String> addressMap;
# Person.hbm.xml
<map name="addressMap" table="person_address_map">
  <key column="personId"></key>
  <map-key type="string" column="_key"/>
  <element type="string" column="_val"/>
</map>

数组: 配置方法和 List 基本一致,不经常使用

# Person.java
private String[] addressArr;
# Person.hbm.xml
<array name="addressArr" table="person_address_arr">
  <key column="personId"/>
  <list-index column="idx"/>
  <element type="string" column="address"/>
</array>

其他注意事项:

  • 在使用集合属性时,类型不能声明为具体的某个实现类,因为 Hibernate 在操作时会将集合转化为自己的实现,如果是具体实现会报错

2. 关联关系配置(实体类型)

一对多 || 多对一配置解析

部门和员工是一对多的关系,部门方(一方)映射配置

# Department
private Set<Employee> employees = new HashSet<Employee>(); 
# Department.hbm.xml
<set name="employees" table="employee" inverse="true">
  <key column="departmentId"/>
  <one-to-many class="Employee" />
</set>

set 节点: 表达的是该属性是少的一方

  • name 属性:实体中属性的名字
  • table 属性:该属性所对应的表名
  • key 子节点:对方表中的外键列
  • on-to-many 子节点:表达的是该列的值为 Employee 类型,且是一对多的关系
  • inverse 属性:默认为 false:表示本方维护关联关系。true:表示本方不维护关联关系。只是影响是否能设置外键列的值(设成有效值或是 null 值),对获取信息没有影响。

员工方(多方)映射配置

# Employee
private Set<Student> students = new HashSet<Student>(); // 关联的学生们
# Employee.hbm.xml
<many-to-one name="department" class="Department" column="departmentId" />

many-to-one 节点:表达的是该属性是多的一方

  • name 属性:实体类中属性名字
  • class 属性:所要关联的是类的名字
  • column 属性:在数据库中存放的名字(外键列,引用关联对象表的主键)

注意: 配置中默认为维护双方的关联关系,若想放弃维护关联关系需要配置 inverse 属性为 true

多对多配置解析

学生和老师是多对多的关系,老师实体映射配置如下:

# Teacher
private Department department;
# Teacher.hbm.xml
<set name="students" table="student_teacher" inverse="false">
  <key column="teacherId"/>
  <many-to-many class="Student" column="studentId" />
</set>

set 节点

  • name 属性:实体类中属性名字
  • class 属性:所要关联的是类的名字
  • column 属性:在数据库中存放的名字(外键列,引用关联对象表的主键)

常见使用技巧

1. 使用 Hibernate 查出没有在实体类中的字段

想带出一些其他的表的数据,但是在要查的表中没有存在这些字段,可以在实体类上加 @Transient 注解,就会过滤掉这些字段

@Transient
public String getItem() {
  return Item;
}
public void setItem(String Item) {
  this.Item = Item;
}

在查询的时候能否自动封装为实体类??

2. 基础表和中间表建表问题

情况:两张表都引用了同一张基础表,且每种情况都是一对多的关系,为两种对应关系都建立相对应的中间表,若是只建立一张中间表,在为中间表添加外键时会出现问题

附页:

表 1:Java 类型与 Hibernate 类型映射表

Hibernat java sql 取值范围
int或integer int 或java.lang.Integer INTEGER 4
long Long或java.lang.Long BIGINT 8
short short Short SMALLINT 2
byte byte Byte TINYINT 1
float float Float FLOAT 4
double double Double DOUBLE 8
big_decimal java.math.BigDecinimal NUMERIC 8位含2位小数部分
character char Character String CHAR(1) 定长字符
string java.lang.String VARCHAR 变长串
boolean boolean或Boolean BIT 布尔
yes_no boolean或Boolean CHAR(1) 布尔
true_false boolean或Boolean CHAR(1) 布尔

表 2:Hiberntae 时间类型表

Hibernate java sql 取值范围
date util.Date sql.Date DATE YYYY-MM-DD
time util.Date sql.Time TIME HH:mm:ss
timestamp util.Date sql.timestamp TIMESTAMP YYYYMMDDHHMMSS
calendar java.util.Calendar TIMESTAMP YYYYMMDDHHMMSS
calendar_date java.util.Calendar DATE YYYY-MM-DD

参考资料:

[传智播客汤阳光老师的 Hibernate 框架教学视频]()

相关文章

相关标签/搜索