90---Hibernate使用方法-----------使用注解完成Hibernate映射

来源:互联网 发布:最好闻的香水知乎 编辑:程序博客网 时间:2024/05/18 02:40

实体和数据库之间存在某种映射关系,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注解(@)定义。

 
本文以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
packagecom.souvc.domain.user;
 
importjava.util.Date;
 
importjavax.persistence.CascadeType;
importjavax.persistence.Column;
importjavax.persistence.Entity;
importjavax.persistence.GeneratedValue;
importjavax.persistence.GenerationType;
importjavax.persistence.Id;
importjavax.persistence.JoinColumn;
importjavax.persistence.ManyToOne;
importjavax.persistence.Table;
importjavax.persistence.Temporal;
importjavax.persistence.TemporalType;
 
importorg.springframework.format.annotation.DateTimeFormat;
/**
* 类名: UserLoginLog
* 描述: 用户登录记录表类
* 开发人员: souvc
* 创建时间:  2015-9-7
* @version V3.0
 */
@Entity
@Table(name = "user_login_log")
publicclass UserLoginLog implementsjava.io.Serializable {
     
    privatestatic final long serialVersionUID = 8686390190132322570L;
     
    privateInteger loginId;
    privateString ip;
    privateString address;
    privateInteger type;
    privateInteger status;
    @DateTimeFormat( pattern = "yyyy-MM-dd HH:mm:ss" )
    privateDate loginTime;
 
    //private UserBaseInfo userBaseInfo;
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "login_id", unique = true, nullable = false)
    publicInteger getLoginId() {
        returnloginId;
    }
 
    publicvoid setLoginId(Integer loginId) {
        this.loginId = loginId;
    }
 
    @Column(name = "ip", nullable = true)
    publicString getIp() {
        returnip;
    }
 
    publicvoid setIp(String ip) {
        this.ip = ip;
    }
 
    @Column(name = "address", nullable = true)
    publicString getAddress() {
        returnaddress;
    }
 
    publicvoid setAddress(String address) {
        this.address = address;
    }
 
    @Column(name = "type", nullable = false)
    publicInteger getType() {
        returntype;
    }
 
    publicvoid setType(Integer type) {
        this.type = type;
    }
 
    @Column(name = "status", nullable = false)
    publicInteger getStatus() {
        returnstatus;
    }
 
    publicvoid setStatus(Integer status) {
        this.status = status;
    }
 
    @Column(name = "login_time", nullable = true)
    @Temporal(TemporalType.TIMESTAMP)
    publicDate getLoginTime() {
        returnloginTime;
    }
 
    publicvoid 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;
//    }
}

 

 
 
 
三、具体注解解释
 
 
 
实体类组件以及注解标签映射关系
 
实体类-----------@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
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)

 

 
b.@Id 注释指定personid属性为表的主键,它可以有多种生成方式:
 
     
 
 
 
?
1
2
3
4
5
6
7
8
9
·TABLE:容器指定用底层的数据表确保唯一。
 
      ·SEQUENCE:使用数据库的SEQUENCE 列来保证唯一
 
      ·IDENTITY:使用数据库的INDENTIT列来保证唯一
 
     ·AUTO:由容器挑选一个合适的方式来保证唯一
 
     ·NONE:容器不负责主键的生成,由调用程序来完成。

 

 
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类中有如下方法:
 
 
 
 
?
1
2
3
4
5
6
7
@ManyToMany(mappedBy = "students")
 
   publicSet<Teacher> getTeachers() {
 
   returnteachers;
 
}

 

 
 
 
那么这里的“students”就是Teachers的一个属性,通常应该是这样的:
 
 
 
Set<Student> students;
 
 
 
另一端的getStudents方法如下所示:
 
 
 
 
?
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")})
 
publicSet<Student> getStudents() {
 
     returnstudents;
 
}

 

 
 
 
@ManyToMany 注释表示Teacher 是多对多关系的一端。
 
@JoinTable 描述了多对多关系的数据表关系。
 
name 属性指定中间表名称,joinColumns 定义中间表与Teacher 表的外键关系。
 
上面的代码中,中间表Teacher_Student的Teacher_ID 列是Teacher 表的主键列对应的外键列,inverseJoinColumns 属性定义了中间表与另外一端(Student)的外键关系。

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);
}
  }
}

0 0
原创粉丝点击