实体和数据库之间存在某种映射关系,hibernate根据这种映射关系完成数据的存取。在程序中这种映射关系由映射文件(*.hbm.xml)或者java注解(@)定义。
本文以java注解的形式总结映射关系配置。
一、导入依赖包。
hibernate-distribution-3.6.5.Final-dist\hibernate-distribution-3.6.5.Final\lib\jpa 目录下的 hibernate-jpa-2.0-api-1.0.0.Final.jar
二、新建实体类
package com.souvc.domain.user;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.springframework.format.annotation.DateTimeFormat;
/**
* 类名: UserLoginLog
* 描述: 用户登录记录表类
* 开发人员: souvc
* 创建时间: 2015-9-7
* @version V3.0
*/
@Entity
@Table(name = "user_login_log")
public class UserLoginLog implements java.io.Serializable {
private static final long serialVersionUID = 8686390190132322570L;
private Integer loginId;
private String ip;
private String address;
private Integer type;
private Integer status;
@DateTimeFormat( pattern = "yyyy-MM-dd HH:mm:ss" )
private Date loginTime;
//private UserBaseInfo userBaseInfo;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "login_id", unique = true, nullable = false)
public Integer getLoginId() {
return loginId;
}
public void setLoginId(Integer loginId) {
this.loginId = loginId;
}
@Column(name = "ip", nullable = true)
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
@Column(name = "address", nullable = true)
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Column(name = "type", nullable = false)
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
@Column(name = "status", nullable = false)
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
@Column(name = "login_time", nullable = true)
@Temporal(TemporalType.TIMESTAMP)
public Date getLoginTime() {
return loginTime;
}
public void setLoginTime(Date loginTime) {
this.loginTime = loginTime;
}
// @ManyToOne(cascade = CascadeType.REFRESH, optional = false)
// @JoinColumn(name = "user_id", unique = true)
// public UserBaseInfo getUserBaseInfo() {
// return userBaseInfo;
// }
//
// public void setUserBaseInfo(UserBaseInfo userBaseInfo) {
// this.userBaseInfo = userBaseInfo;
// }
}
View Code
三、具体注解解释
实体类组件以及注解标签映射关系
实体类-----------@Entity/@Table----------数据表
Id--------------@Id----------主键
普通属性---------@Column----------普通键
集合属性---------@OneToMany/@ManyToOne/@ManyToMany/@OneToOne----------外键
A.写在类声明之前的有:
a.@Entity,以表明此Bean为EntityBean。每一个持久化POJO类都是一个实体bean,这可以通过在类的定义中使用@Entity注解来进行声明。name 为可选 , 对应数据库中一的个表
b.@Table (name=”TableName”),表示此实体Bean对应的数据库表名。
@Table是类一级的注解, 通过@Table注解可以为实体bean映射指定表(table),目录(catalog)和schema的名字.
@Table,那么系统自动使用默认值:实体的短类名(不附带包名).@Table元素包括了一个schema 和一个 catalog属性,如果需要可以指定相应的值. 结合使用@UniqueConstraint注解可以定义表的唯一约束(unique constraint)
B.写在getXxx()方法声明之前的有:
a.@Column注释定义了映射到列的所有属性,如列名是否唯一,是否允许为空,是否允许更新等,他的属性介绍如下:
(1) name 可选,列名(默认值是属性名)
(2) unique 可选,是否在该列上设置唯一约束(默认值false)
(3) nullable 可选,是否设置该列的值可以为空(默认值false)
(4) insertable 可选,该列是否作为生成的insert语句中的一个列(默认值true)
(5) updatable 可选,该列是否作为生成的update语句中的一个列(默认值true)
(6) columnDefinition 可选: 为这个特定列覆盖SQL DDL片段 (这可能导致无法在不同数据库间移植)
(7) table 可选,定义对应的表(默认为主表)
(8) length 可选,列长度(默认值255)
(8) precision 可选,列十进制精度(decimal precision)(默认值0)
(10) scale 可选,如果列十进制数值范围(decimal scale)可用,在此设置(默认值0)
b.@Id 注释指定personid属性为表的主键,它可以有多种生成方式:
@id 定义了映射到数据库表的主键的属性 , 一个实体只能有一个属性被映射为主键 . 置于 getXxxx() 前 .
·TABLE:容器指定用底层的数据表确保唯一。
·SEQUENCE:使用数据库的SEQUENCE 列来保证唯一
·IDENTITY:使用数据库的INDENTIT列来保证唯一
·AUTO:由容器挑选一个合适的方式来保证唯一
·NONE:容器不负责主键的生成,由调用程序来完成。
View Code
c.@GeneratedValue注释定义标识字段的生成方式。
@GeneratedValue(strategy=GenerationType,generator="")
strategy: 表示主键生成策略 , 有 AUTO,INDENTITY,SEQUENCE 和 TABLE 4 种 , 分别表示让 ORM 框架自动选择,
根据数据库的 Identity 字段生成 ,
根据数据库表的 Sequence 字段生成 ,
以有根据一个额外的表生成主键 , 默认为AUTO
generator: 表示主键生成器的名称 , 这个属性通常和 ORM 框架相关 , 例如 ,Hibernate 可以指定 uuid 等主键生成方式 .
示例 :
@Id
@GeneratedValues(strategy=StrategyType.SEQUENCE)
public int getPk() {
return pk;
}
d. @Version 映射版本号属性
e. @Column 指定属性对应的列的信息
可选
@Column 描述了数据库表中该字段的详细定义 , 这对于根据 JPA 注解生成数据库表结构的工具非常有作用 .
name: 表示数据库表中该字段的名称 , 默认情形属性名称一致
nullable: 表示该字段是否允许为 null, 默认为 true
unique: 表示该字段是否是唯一标识 , 默认为 false
length: 表示该字段的大小 , 仅对 String 类型的字段有效
insertable: 表示在 ORM 框架执行插入操作时 , 该字段是否应出现 INSETRT 语句中 , 默认为 true
updateable: 表示在 ORM 框架执行更新操作时 , 该字段是否应该出现在 UPDATE 语句中 , 默认为 true. 对于一经创建就不可以更改的字段 , 该属性非常有用 , 如对于 birthday 字段 .
columnDefinition: 表示该字段在数据库中的实际类型 . 通常 ORM 框架可以根据属性类型自动判断数据库中字段的类型 , 但是对于 Date 类型仍无法确定数据库中字段类型究竟是 DATE,TIME 还是 TIMESTAMP. 此外 ,String 的默认映射类型为 VARCHAR, 如果要将 String 类型映射到特定数据库的 BLOB 或 TEXT 字段类型 , 该属性非常有用 .
示例 :
@Column(name="BIRTH",nullable="false",columnDefinition="DATE")
public String getBithday() {
return birthday;
}
f . @Temporal 指定日期时间的类型(TIMESTAMP,DATE,TIME)
g. 简单属性可以不用注解。默认就是@Basic
h. @Transient 指定属性不需要映射
可选
@Transient 表示该属性并非一个到数据库表的字段的映射 ,ORM 框架将忽略该属性 .
如果一个属性并非数据库表的字段映射 , 就务必将其标示为 @Transient, 否则 ,ORM 框架默认其注解为 @Basic
示例 :
// 根据 birth 计算出 age 属性
@Transient
public int getAge() {
return getYear(new Date()) - getYear(birth);
}
i. 复杂属性:关联,继承,组件,联合主键,集合
C.关系/对象映射
A.一对多:
@OneToMany指明关联关系为一对多关系,下面是@OneToMany 注释的属性:
1>targetEntity
Class 类型的属性。定义关系类的类型,默认是该成员属性对应的类类型,所以通常不需要提供定义。
2>mappedBy
String 类型的属性。定义类之间的双向关系。如果类之间是单向关系,不需要提供定义,如果类和类之间形成双向关系,我们就需要使用这个属性进行定义,否则可能引起数据一致性的问题。
3>cascade
CascadeType[]类型。
该属性定义类和类之间的级联关系。定义的级联关系将被容器视为对当前类对象及其关联类对象采取相同的操作,而且这种关系是递归调用的。
举个例 子:Order 和OrderItem 有级联关系,那么删除Order 时将同时删除它所对应的OrderItem对象。而如果OrderItem还和其他的对象之间有级联关系,那么这样的操作会一直递归执行下去。
cascade 的值只能从:
CascadeType.PERSIST(级联新建);
CascadeType.REMOVE(级联删除);
CascadeType.REFRESH(级联刷新);
CascadeType.MERGE(级联更新)中选择一个或多个。
还有一个选择是使用CascadeType.ALL,表示选择全部四项。
4>fatch
FetchType 类型的属性。
可选择项包括:FetchType.EAGER和FetchType.LAZY。
前者表示关系类(本例是OrderItem类)在主类(本例是Order类)加载的时候同时加载;
后者表示关系类在被访问时才加载。默认值是FetchType. LAZY。
@OrderBy(value = "id ASC")注释指明加载OrderItem 时按id 的升序排序。
B.多对一:
@ManyToOne注释,有四个属性:targetEntity、cascade、fetch 和optional。
前三个属性的具体含义和@OneToMany注释的同名属性相同,但@ManyToOne 注释的fetch 属性默认值是FetchType.EAGER。
optional 属性是定义该关联类对是否必须存在,值为false 时,关联类双方都必须存在,如果关系被维护端不存在,查询的结果为null。值为true 时, 关系被维护端可以不存在,查询的结果仍然会返回关系维护端,在关系维护端中指向关系被维护端的属性为null。
optional属性的默认值是true。
举个例:某项订单(Order)中没有订单项(OrderItem),如果optional 属性设置为false,获取该项订单(Order)时,得到的结果为null,如果optional属性设置为true,仍然可以获取该项订单,但订单中 指向订单项的属性为null。
实际上在解释Order 与OrderItem的关系成SQL时,optional属性指定了他们的联接关系
optional=false 联接关系为inner join,
optional=true 联接关系为left join。
@JoinColumn(name = "order_id")注释指定OrderItem 映射表的order_id 列作为外键与Order 映射表的主键列关联。
可选
@ManyToOne 表示一个多对一的映射 , 该注解标注的属性通常是数据库表的外键
optional: 是否允许该字段为 null, 该属性应该根据数据库表的外键约束来确定 , 默认为 true
fetch: 表示抓取策略 , 默认为 FetchType.EAGER
cascade: 表示默认的级联操作策略 , 可以指定为 ALL,PERSIST,MERGE,REFRESH 和 REMOVE 中的若干组合 , 默认为无级联操作
targetEntity: 表示该属性关联的实体类型 . 该属性通常不必指定 ,ORM 框架根据属性类型自动判断targetEntity.
示例 :
// 订单 Order 和用户 User 是一个 ManyToOne 的关系
// 在 Order 类中定义
@ManyToOne()
@JoinColumn(name="USER")
public User getUser() {
return user;
}
C.一对一:
@OneToOne 注释,有五个属性:targetEntity、cascade、fetch、optional 和mappedBy 。
前四个属性的具体含义与@ManyToOne 注释的同名属性一一对应, fetch 属性默认值是FetchType.EAGER。
mappedBy属性的具体含义与@OneToMany 注释的同名属性相同。
如果optional = true 设置表明此属性可以为null。
例如在身份证的处理时可以这样设置,因为未成年人就是没有身份证的。
D.多对多:
@ManyToMany 注释:表示此类是多对多关系的一边,mappedBy 属性定义了此类为双向关系的维护端,注意:mappedBy 属性的值为此关系的另一端的属性名。
例如,在Student类中有如下方法:
@ManyToMany(mappedBy = "students")
public Set<Teacher> getTeachers() {
return teachers;
}
那么这里的“students”就是Teachers的一个属性,通常应该是这样的:
Set<Student> students;
另一端的getStudents方法如下所示:
@ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinTable(name = "Teacher_Student",joinColumns = {@JoinColumn(name = "Teacher_ID", referencedColumnName = "teacherid")},inverseJoinColumns = {@JoinColumn(name = "Student_ID", referencedColumnName ="studentid")})
public Set<Student> getStudents() {
return students;
}
@ManyToMany 注释表示Teacher 是多对多关系的一端。
@JoinTable 描述了多对多关系的数据表关系。
name 属性指定中间表名称,joinColumns 定义中间表与Teacher 表的外键关系。
上面的代码中,中间表Teacher_Student的Teacher_ID 列是Teacher 表的主键列对应的外键列,inverseJoinColumns 属性定义了中间表与另外一端(Student)的外键关系。
可以参照中文官方文档: http://docs.jboss.org/hibernate/annotations/3.4/reference/zh_cn/html_single/