实体和数据库之间存在某种映射关系,hibernate根据这种映射关系完成数据的存取。在程序中这种映射关系由映射文件(*.hbm.xml)或者java注解(@)定义。
本文以java注解的形式总结映射关系配置。
实体类组件以及注解标签映射关系
实体类-----------@Entity/@Table----------数据表
Id--------------@Id----------主键
普通属性---------@Column----------普通键
集合属性---------@OneToMany/@ManyToOne/@ManyToMany/@OneToOne/@OneToMany----------外键
将映射文件配置到hibernate配置文件
Hibernate将通过配置文件(cfg.xml)定义实体和数据库关系映射
<mapping class="com.test.Cat"/>
主键映射
.Hibernate推荐实体类有主键列并且有setter 和 getter,且主键数据类型使用引用类型。因为,基础数据类型不能为null值,hibernate中主键的null表明实体类是处在瞬时(Transient)状态,非null表示处持久化()状态。
.用@Id声明为主键列,用@Column声明列名。
.列名属性名相同时候@Column可以省略。
.@GeneratedValue指定主键的生成策略
Example:
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
主键生成规则
目前@注解支持4种生成策略:
GenerationType.AUTO:根据数据库自己决定
GenerationType.TABLE:使用指定表决定主键的取值
GenerationType.SEQUENCE:使用sequence决定主键取值,适合支持sequence的数据库。
GenerationType.IDENTITY:identity类型的主键
普通属性配置
.java@注解使用@Column和@Basic配置普通属性。两者都可以省略
.@Column属性(声明字段约束)
Nullable非空约束
Unique 唯一约束
Insertable 插入约束(是否允许插入)
Updateable 更新约束(是否允许更新)
Length 列长度
ColumnDefinition 列类型
Scale 整数长度
Precision 小数点精度
@Basic属性(声明加载方式)
Fetch 是否延迟加载
Optional 该列是否可以为null
Example:
@Column(name = "salary", scale = 8, precision = 2)
@Basic(fetch = FetchType.LAZY, optional=true)
private double salary;
日期属性配置
日期属性也是普通属性
除了@column和@Basic之外还可得使用@Temporal配置日期类型
java.sql.Date/java.sql.Time/java.sql.Timestamp都是java.util.Date的子类。实体类中声明成java.util.Date就行了。Hibernate根据日期配置的具体类型操作数据库。
Example:
@Temporal(TemporalType.TIMESTAMP)
// 日期类型(DATE, TIME还是TIMESTEMP)
@Column(name = "createDate")
private Date createDate;
临时属性映射
临时属性是实体类中方便运算的成员,不参与数据库的映射。防止hibernate把它和数据库进行映射导致产生异常,使用@Transient标记。
可以配置在属性上也可以配置在对应的getter/setter方法上。
Example:
@Transient
Public setterTemp (String temp){
this.temp = temp;
}
版本属性映射
为了保证数据的准确性,程序必须保证只用一个线程同时访问数据。乐观锁和悲观锁是两种实现的方式。@Version是乐观锁的实现。版本列一般为数字列。
Example:
@Version
Private int id;
实体关系映射配置
见《Hibernate实体映射配置2(java@注解方式)》
==================================================
1.使用注解完成映射使用Hibernate注解的步骤如下:
添加jar包 使用注解配置持久化类以及对象关联关系使用AnnotationConfiguration建立SessionFactory
在Hibernate配置文件(hibernate.cfg.xml)中声明持久化类
2.相关的注解
@Entity 将一个类声明为一个持久化类
@Id 声明了持久化类的标识属性
@GeneratedValue 定义标识属性值的生成策略
@Table(name = "EMP")<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">为持久化类映射指定表</span>
@Column
将属性映射到列(字段)
@Transient 将忽略这些属性
@OneToOne 建立持久化类之间的一对一关联关系
@OneToMany 建立持久化类之间的一对多关联关系
@ManyToOne 建立持久化类之间的多对一关联关系
@ManyToMany 建立持久化类之间的多对多关联关系
3.使用注解可以配置命名查询。配置命名查询的注解为@NamedQuery
@Entity
@Table(name = "EMP")
@NamedQuery(name = "selectEmp", query = "from Emp where empName like :ename")
public class Emp implements java.io.Serializable {
//缺省其他代码
}
============================================================
关系由映射文件(*.hbm.xml)或者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
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
|
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;
// }
}
|
1
2
3
4
5
6
7
8
9
10
11
|
(
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
)
|
1
2
3
4
5
6
7
8
9
|
·TABLE:容器指定用底层的数据表确保唯一。
·SEQUENCE:使用数据库的SEQUENCE 列来保证唯一
·IDENTITY:使用数据库的INDENTIT列来保证唯一
·AUTO:由容器挑选一个合适的方式来保证唯一
·NONE:容器不负责主键的生成,由调用程序来完成。
|
1
2
3
4
5
6
7
|
@ManyToMany
(mappedBy =
"students"
)
public
Set<Teacher> getTeachers() {
return
teachers;
}
|
1
2
3
4
5
6
7
8
9
|
@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;
}
|
1.导入jar包:ojdbc5.jar
==================================================================================================
2.使用注解配置持久化类以及对象关联关系,利用反响工程建立注解文件
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="dialect">
org.hibernate.dialect.Oracle9Dialect
</property>
<property name="connection.url">
jdbc:oracle:thin:@localhost:1521:orcl
</property>
<property name="connection.username">scott</property>
<property name="connection.password">tiger</property>
<property name="connection.driver_class">
oracle.jdbc.OracleDriver
</property>
<property name="myeclipse.connection.profile">hr</property>
<mapping class="com.yh.entity.Emp" />
</session-factory>
</hibernate-configuration>
==================================================================================================
3.HibernateSessionFactory相关修改
package com.yh.xx.dao;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
/**
* Configures and provides access to Hibernate sessions, tied to the
* current thread of execution. Follows the Thread Local Session
* pattern, see {@link http://hibernate.org/42.html }.
*/
public class HibernateSessionFactory {
/**
* Location of hibernate.cfg.xml file.
* Location should be on the classpath as Hibernate uses
* #resourceAsStream style lookup for its configuration file.
* The default classpath location of the hibernate config file is
* in the default package. Use #setConfigFile() to update
* the location of the configuration file for the current session.
*/
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private static Configuration configuration = new AnnotationConfiguration();
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;
static {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
private HibernateSessionFactory() {
}
/**
* Returns the ThreadLocal Session instance. Lazy initialize
* the <code>SessionFactory</code> if needed.
*
* @return Session
* @throws HibernateException
*/
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();
if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}
return session;
}
/**
* Rebuild hibernate session factory
*
*/
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
/**
* Close the single hibernate session instance.
*
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
/**
* return session factory
*
*/
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* return session factory
*
* session factory will be rebuilded in the next call
*/
public static void setConfigFile(String configFile) {
HibernateSessionFactory.configFile = configFile;
sessionFactory = null;
}
/**
* return hibernate configuration
*
*/
public static Configuration getConfiguration() {
return configuration;
}
}
==================================================================================================
4.建立观察实体类测试
package com.yh.entity;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
/**
* Emp entity. @author MyEclipse Persistence Tools
*/
@Entity
@Table(name = "EMP", schema = "SCOTT")
public class Emp extends Person implements java.io.Serializable {
// Fields
@My
private Short empno;
private String ename;
private String job;
private Short mgr;
private Date hiredate;
private Double sal;
private Double comm;
private Byte deptno;
// Constructors
@Override
@Deprecated
public void say(){
Week w=Week.Fri;
System.out.println(w);
}
/** default constructor */
public Emp() {
}
/** minimal constructor */
public Emp(Short empno) {
this.empno = empno;
}
/** full constructor */
public Emp(Short empno, String ename, String job, Short mgr, Date hiredate,
Double sal, Double comm, Byte deptno) {
this.empno = empno;
this.ename = ename;
this.job = job;
this.mgr = mgr;
this.hiredate = hiredate;
this.sal = sal;
this.comm = comm;
this.deptno = deptno;
}
// Property accessors
@Id
@Column(name = "EMPNO", nullable = false, precision = 4, scale = 0)
public Short getEmpno() {
return this.empno;
}
public void setEmpno(Short empno) {
this.empno = empno;
}
@Column(name = "ENAME", length = 10)
public String getEname() {
return this.ename;
}
public void setEname(String ename) {
this.ename = ename;
}
@Column(name = "JOB", length = 9)
public String getJob() {
return this.job;
}
public void setJob(String job) {
this.job = job;
}
@Column(name = "MGR", precision = 4, scale = 0)
public Short getMgr() {
return this.mgr;
}
public void setMgr(Short mgr) {
this.mgr = mgr;
}
@Temporal(TemporalType.DATE)
@Column(name = "HIREDATE", length = 7)
public Date getHiredate() {
return this.hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
@Column(name = "SAL", precision = 7)
public Double getSal() {
return this.sal;
}
public void setSal(Double sal) {
this.sal = sal;
}
@Column(name = "COMM", precision = 7)
public Double getComm() {
return this.comm;
}
public void setComm(Double comm) {
this.comm = comm;
}
@Column(name = "DEPTNO", precision = 2, scale = 0)
public Byte getDeptno() {
return this.deptno;
}
public void setDeptno(Byte deptno) {
this.deptno = deptno;
}
}
==================================================================================================
5.测试类
public class EmpTest {
@Test
public void empList(){
Session session=HibernateSessionFactory.getSession();
List<String> ns=session.createSQLQuery("select ename from emp").list();
for (String string : ns) {
System.out.println(string);
}
}
}