Hibernate是一个对象关系映射(ORM)框架,对JDBC进行了轻量级的对象封装,将POJO与数据库表建立映射关系。
Hibernate的映射可以分为三个方面:类,属性,关系。而这些映射可以通过两种不同的方式来进行:XML配置,注解。
注解与配置分析
注解更加简单不繁琐,直接写在代码中,内聚性更强。
配置实用xml的形式,不在代码中。发生变化的时候,不需要重新编译。
Hibernate与JPA
JPA,Java Persistence API(Java持久化接口)。JPA注解是Java EE的规范和标准。
JPA是标准,Hibernate是JPA的一种具体实现,Hibernate比JPA更加强大,是JPA的超集。
Hibernate通过hibernate-annotation,hibernate-entitymanager,hibernate-core三个组件来实现。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
实际开发中,优先实用JPA注解,利于扩展和移植。
hibernate.cfg.xml
hibernate的配置文件,配置了数据库的相关属性(url,driver_class,username,password,dialect等等),另外还有对应的对象关系映射(使用注解的时候mapping使用class属性,使用配置的时候mapping使用resource属性)。
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hdindex?useUnicode=true&amp;characterEncoding=UTF-8</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>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<mapping class="com.hdzbk.template.entity.NormItem"/>
<mapping class="com.hdzbk.template.entity.Resource"/>
<mapping class="com.hdzbk.template.entity.TradeType"/>
<mapping class="com.hdzbk.template.entity.NormEconomicIndex"/>
<mapping class="com.hdzbk.template.entity.NormQuantityIndex"/>
<mapping class="com.hdzbk.template.entity.MeasureEconomicIndex"/>
<mapping class="com.hdzbk.template.entity.MainLMMIndex"/>
</session-factory>
</hibernate-configuration>
类注解
@Entity
- 映射实体类;
- 有一个可选的name属性,对应数据库中的一个表;若表名与实体类名相同,则可以省略;
- 需要制定实体类的主键属性。
@Table
- 与@Entity配合使用,仅能标注在实体的class定义处,表示实体对应的数据表的信息;
- @Table(name=”“,catalog=”“,schema=”“);name可选,表示映射表的名称,表名与实体类名不一致的时候才需要指定;catalog可选,表示Catalog的名称;schema可选,表示Schema名称;
- 数据库系统包含多个Catalog表示目录,每个Catalog包含多个Schema表示模式,每个Schema包含多个数据库对象(表、视图、字段等);
- 各种数据库系统对Catalog和Schema的支持各不相同;
- MySQL不支持Catalog,Schema代表数据库的名称;
@Entity
@Table(name="normitem")
public class NormItem {
private String normitem_id;
private int dbid;
private int dbitemid;
private String code;
private String description;
private String spec;
private String unit;
private DBInfo dbInfo;
private NormEconomicIndex normEconomicIndex;
private NormQuantityIndex normQuantityIndex;
@Embeddable
- 表示不是一个实体类,而是一个实体类;该类的对象在另一个实体类中充当属性;
- 当多个实体类有一些共有的属性时,可以使用Embeddable注解;
- 联合主键时,也可以使用Embeddable注解,与EmbeddedId属性注解或IdClass类注解配合使用;
属性注解
属性注解的两种添加方式:写在属性字段上,写在属性字段的getter方法上。
@Id
- 实体类中必须的注解,映射到数据库表的主键属性;
- 一个实体类可以有多个属性被映射为主键;
- 如果有多个主键,实体类需要实现Serializable接口(声明式接口);
@GeneratedValue
- 两个属性:strategy,generator;
- strategy表示主键生成策略,有四种取值:GenerationType.AUTO(根据底层数据库自动选择,默认值);GenerationType.INDENTITY(根据数据库的Identity字段生成);GenerationType.SEQUENCE(使用Sequence来决定主键的取值);GenerationType.TABLE(使用指定表来决定主键取值),结合@TableGenerator使用;
- generator属性表示主键生成器的名称,这个主键通常和ORM框架相关;例如Hibernate可以指定uuid等主键生成方式;
@Column
- 将属性映射到数据库表的列,使用该注解来覆盖默认值;
- 描述了数据库表中该字段的详细定义,对于根据JPA注解生成数据库表结构的工具非常有用;
- 属性name:可选,表示数据库表中对应列的名称,默认时与属性名一致;
- 属性nullable,可选,是否允许为null,默认true;
- 属性unique,可选,是否唯一,默认false;
- 属性length,可选,表示字段大小;仅对String类型字段有效,默认值255;
- 属性insertable,可选,表示ORM框架执行插入操作时,该字段是否应该出现在INSERT语句中,默认true;
- 属性updateable,可选,表示ORM框架执行更新操作时,该字段是否应该出现在UPDATE语句中,默认为true;
@Embedded
- 与Embeddable注解配合使用;
- 用于嵌入类类型的属性;
@EmbeddedId
- 与Embeddable注解配合使用,一般用于定义联合主键;
- 嵌入式的主键类必须实现Serializable接口,必须有默认的public无参构造方法,必须覆盖equals和hashCode方法;
@Transient
- 可选的注解,表示该属性并不映射到一个数据库表的字段;
- ORM框架将忽略该属性;
- 如果一个属性并不映射到数据库表的字段,要将其注解为@Transient,否则ORM框架默认注解其为@Basic;
另外的几个注解:
@Lob:String类型属性在MySQL中映射产生的字段是longtext;Byte[]类型属性在MySQL中映射产生的字段是longblob;
@Version:主要用于处理并发操作;
@Basic:两个属性,fetch,optional;前者表示加载方式(EAGER,LAZY),后者表示是否允许为空;
@SequenceGenerator:用于序列式的主键生成策略;
范例:
实体类如下(请暂时忽略关系映射部分):
@Entity
@Table(name="normitem")
public class NormItem {
private String normitem_id;
private int dbid;
private int dbitemid;
private String code;
private String description;
private String spec;
private String unit;
private DBInfo dbInfo;
private NormEconomicIndex normEconomicIndex;
private NormQuantityIndex normQuantityIndex;
public NormItem() {
}
public NormItem(int dbid, int dbitemid, String code, String description, String spec, String unit, DBInfo dbInfo, NormEconomicIndex normEconomicIndex, NormQuantityIndex normQuantityIndex) {
this.dbid = dbid;
this.dbitemid = dbitemid;
this.code = code;
this.description = description;
this.spec = spec;
this.unit = unit;
this.dbInfo = dbInfo;
this.normEconomicIndex = normEconomicIndex;
this.normQuantityIndex = normQuantityIndex;
}
@Id
@GeneratedValue(generator = "idGenerator")
@GenericGenerator(name = "idGenerator", strategy = "uuid")
@Column(length = 32)
public String getNormitem_id() {
return normitem_id;
}
public void setNormitem_id(String normitem_id) {
this.normitem_id = normitem_id;
}
public int getDbid() {
return dbid;
}
public void setDbid(int dbid) {
this.dbid = dbid;
}
public int getDbitemid() {
return dbitemid;
}
public void setDbitemid(int dbitemid) {
this.dbitemid = dbitemid;
}
@Transient
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Transient
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Transient
public String getSpec() {
return spec;
}
public void setSpec(String spec) {
this.spec = spec;
}
@Transient
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "dbid")
public DBInfo getDbInfo() {
return dbInfo;
}
public void setDbInfo(DBInfo dbInfo) {
this.dbInfo = dbInfo;
}
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "norm_economic_index_id")
public NormEconomicIndex getNormEconomicIndex() {
return normEconomicIndex;
}
public void setNormEconomicIndex(NormEconomicIndex normEconomicIndex) {
this.normEconomicIndex = normEconomicIndex;
}
@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "norm_quantity_index_id")
public NormQuantityIndex getNormQuantityIndex() {
return normQuantityIndex;
}
public void setNormQuantityIndex(NormQuantityIndex normQuantityIndex) {
this.normQuantityIndex = normQuantityIndex;
}
}
Hibernate的建表语句如下:
create table normitem (normitem_id varchar(32) not null, dbid integer not null, dbitemid integer not null, norm_economic_index_id varchar(32), norm_quantity_index_id varchar(32), primary key (normitem_id))
alter table normitem add constraint FK_n7f3b2934vk1qsbbwf1ukp1sq foreign key (dbid) references dbinfo (dbinfo_id)
alter table normitem add constraint FK_9fuf4154ldlh62wjsojss6bnh foreign key (norm_economic_index_id) references normeconomicindexdict (norm_economic_index_id)
alter table normitem add constraint FK_4edd7y2pykyqgqx3yod48t9vc foreign key (norm_quantity_index_id) references normquantityindexdict (norm_quantity_index_id)