你的位置:首页 > Java教程

[Java教程]Hibernate基于注解方式配置来实现实体和数据库之间存在某种映射关系


实体和数据库之间存在某种映射关系,hibernate根据这种映射关系完成数据的存取。在程序中这种映射关系由映射文件(*.hbm.

本文以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注解来进行声明。

    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属性为表的主键,它可以有多种生成方式:

     

·TABLE:容器指定用底层的数据表确保唯一。   ·SEQUENCE:使用数据库的SEQUENCE 列来保证唯一   ·IDENTITY:使用数据库的INDENTIT列来保证唯一   ·AUTO:由容器挑选一个合适的方式来保证唯一   ·NONE:容器不负责主键的生成,由调用程序来完成。 

View Code

 

c.@GeneratedValue注释定义标识字段的生成方式。

d. @Version 映射版本号属性

e.  @Column 指定属性对应的列的信息

f . @Temporal 指定日期时间的类型(TIMESTAMP,DATE,TIME)

g. 简单属性可以不用注解。默认就是@Basic

h. @Transient 指定属性不需要映射

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 映射表的主键列关联。

 

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/