Hibernate学习

1        Hibernate核心技术

1.1        理论基础

操作数据库的3个阶段

1、  操作JDBC阶段

2、  封装JDBC

3、  ORM阶段

ORM对象关系映射

持久层概念

 

1.2        Hibernate开发流程

步骤

1、  创建Hibernate的配置文件:该文件负责初始化Hibernate配置,包括数据库配置和映射文件配置

2、  创建Hibernate映射文件:每一个数据表对应一个映射文件,该文件描述了数据库中表的信息,也描述了对应的持久化类的信息

3、  创建持久化类

以上三步是开发Hibernate要实现的关键内容,接下来就要面向Web应用层进行编码

1、  编写DAO层:通过HibernateAPI编写访问数据库的代码

2、  编写Service层:编写业务层实现,调用DAO层类代码

 

下载并安装Hibernate

必需的包:

Hibernate3.jar

cglib-2.1.jarasm-attrs.jarasm.jarCGLIB库,用来实现PO字节码的动态生成

dom4j-1.5.2.jarjavaXMLAPI,类似于jdom,用来读写XML文件的

commons-collections-2.1.1.jar

commons-logging-1.0.4.jarlog4j-1.2.9.jar:包含了日志功能

将以上文件复制到lib目录下

 

1.3        Hibernate配置文件详解

有两种形式:一种是XML(hibernate.cfg.xml),一种是properties属性文件(hibernate.properties),一般使用XML

Etc子目录下提供了默认的Hibernate配置文件hibernate.cfg.xml,复制到src目录下,修改后如下

<hibernate-configuration>

     <session-factory name="foo">

         <property name="myeclipse.connection.profile">JDBC for MySQL</property>

         <!-- 显示执行的SQL语句 -->

         <property name="show_sql">true</property>

         <property name="connection.url">jdbc:mysql://localhost:3306/demo</property>

         <property name="connection.username">root</property>

         <property name="connection.password"></property>

         <property name="connection.drive_class">org.gjt.mm.mysql.Driver</property>

         <!-- 选择使用的方言 -->

         <property name="dialect">org.hibernate.dialect.MySQLDialect</property>

         <!-- 映射文件 -->

         <mapping resource="com/demo/hibernate/beans/User.hbm.xml"/>

     </session-factory>

</hibernate-configuration>

 

1.4        编写映射文件User.hbm.xml

Hibernate映射文件包含了对象/关系映射(O/R Mapping)所需的元数据。建立一个映射文件User.hbm.xml来映射到数据库表User,映射的类名为User,所在的包为com.demo.hibernate.beans。如下

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC

     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >

<hibernate-mapping package="com.demo.hibernate.beans">

     <class name="User" table="user">

         <id name="id" column="ID" type="integer">

              <generator class="native"/>               //设置主键生成方式

         </id>

         <property name="username" column="username" type="string"/>

         <property name="password" column="password" type="string"/>

         <property name="email" column="email" type="string"/>  

     </class>

</hibernate-mapping>

 

1.4.1       根元素<hibernate-mapping>

每一个hbm.xml文件都有唯一的一个根元素。Package属性指定一个包前缀。<hibernate-mapping>元素允许嵌套多个<class>映射。但是最好的做法是一个持久化类对应一个映射文件,并以持久化的超类名称命名

 

1.4.2       使用<class>定义类

<class name="User" table="user">

Class也可以是一个接口,之后可以用<subclass>来指定该接口的实际实现类。

 

1.4.3       使用<id>定义主键

如果表使用联合主键,你可以映射多个属性为标识符属性。下面定义了两个字段作为联合主键。此时持久化类必须重载equals()hashCode()方法,来实现组合标识符的相等判断。

<composite-id>

    <key-property name="username"/>

    <key-property name="password"/>

</composite-id>

 

1.4.4       <generator>设置主键生成方式

<generator class="native"/>

 

1.4.5       Hibernate映射类型

 

1.4.6       使用<property>定义属性

<property name="username" column="username" type="string"/>

 

1.4.7       <many-to-one>配置多对一映射

1.4.8       <one-to-one>配置一对一映射

1.4.9       Hibernate映射文件自动生成工具

 

 

1.5        编写持久化类User.java

持久化类是指其实例需要被Hibernate持久化到数据库中的类。Hibernate使用简单的Java对象(Plain Old Java Objects,就是POJOs,有时也称作Plain Ordinary Java Objects)这种编程模型来进行持久化

package com.demo.hibernate.beans;

public class User {

     private java.lang.Integer id;

     private String username;

     private String password;

     private String email;

     public String getEmail() {

         return email;

     }

     public void setEmail(String email) {

         this.email = email;

     }

     ……

}

getXXX()setXXX()方法必须符合特定的命名规则,“get”和“set”后面紧跟属性的名字,并且属性名的首字母为大写。

如果持久化类的属性为boolean类型,那么它的get方法即可以用get为前缀,也可以用“is”为前缀。

 

1.6        编写辅助类HibernateSessionFactory.java

Session是一个持久化管理器,我们通过它来从数据加中存取User。首先,我们要从SessionFactory中获取一个Session。通过对configure()调用来装载hibernate.cfg.xml配置文件,并初始化成一个Configuration实例。

通常SessionFactory只是被初始化一次,例如通过一个load-on-startup servlet来初始化。这意味着你不应该在servlet中把它作为一个实例变量来持有,而应该放在其他地方。进一步说,我们需要使用单例(Singleton)模式,才能更容易地在程序中访问SessionFactory。下面的方法就同时解决了这两个问题

 

package com.demo.hibernate.util;

import org.hibernate.cfg.Configuration;

import org.hibernate.HibernateException;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

 

public class HibernateSessionFactory {

     private static String CONFIG_FILE_LOCATION="/hibernate.cfg.xml";

     private static final ThreadLocal threadLocal=new ThreadLocal();

     private static final Configuration cfg=new Configuration();

     private static SessionFactory sessionFactory;

     //取得session

     public static Session currentSession() throws HibernateException{

         Session session=(Session)threadLocal.get();

         if(session==null){

              if(sessionFactory==null){

                   try{

                       cfg.configure(CONFIG_FILE_LOCATION);

                       sessionFactory=cfg.buildSessionFactory();

                   }catch(Exception e){

                       System.err.println("%%%%Error Creating SessionFactory%%%%");

                       e.printStackTrace();

                   }

              }

              session=sessionFactory.openSession();

              threadLocal.set(session);

         }

         return session;

     }

     //关闭Session对象

     public static void closeSession() throws HibernateException{

         Session session=(Session)threadLocal.get();

         threadLocal.set(null);

         if(session==null){

              session.close();

         }

     }

}

这个类不但在它的静态初始器中使用了SessionFactory,还使用了一个ThreadLocal变量来保存Session作为当前工作线程。

 

1.7        编写DAOUserDAO.java

所谓的DAO(Data Access Object)层,就是数据访问接口,为了基于Hibernate的开发中,通常将业务层与数据层分开,DAO层只负责调用Hibernate API实现CRUD操作,Service层面向用户负责调用DAO层的代码。这样做的好处是,数据层的代码不用关心业务,可以更好地实现移植

    下面编写一个DAOUserDAO.java,该类实现一个getUser()函数,根据用户名username查询一个用户对象。

public class UserDAO {

     public User getUser(String username)throws HibernateException{

         Session session=null;

         Transaction tx=null;

         User user=null;

         try{

              session=HibernateSessionFactory.currentSession();

              tx=session.beginTransaction();

              Query query=session.createQuery("from User where username=?");

              query.setString(0, username.trim());

              user=(User)query.uniqueResult();

              query=null;

              tx.commit();

             

         }catch(HibernateException e){

              throw e;

         }finally{

              if(tx!=null){

                   tx.rollback();

              }

              HibernateSessionFactory.closeSession();

         }

         return user;

     }

}

 

1.8        编写Service类并运行

即服务层,就是面向用户服务,它定义的方法都是与实际的业务相关的。

下面定义一个ServiceUserService,它有一个函数valid(),根据用户名和密码来判断用户是否存在。

 

运行出错

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial

      at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645)

      at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:247)

      at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:284)

      at javax.naming.InitialContext.getNameParser(InitialContext.java:439)

      at org.hibernate.util.NamingHelper.bind(NamingHelper.java:52)

      at org.hibernate.impl.SessionFactoryObjectFactory.addInstance(SessionFactoryObjectFactory.java:90)

      at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:306)

      at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1294)

      at com.demo.hibernate.util.HibernateSessionFactory.currentSession(HibernateSessionFactory.java:19)

      at com.demo.hibernate.dao.UserDAO.getUser(UserDAO.java:16)

      at com.demo.hibernate.service.UserService.valid(UserService.java:8)

      at com.demo.hibernate.service.UserService.main(UserService.java:19)

原因:配置文件在存在<session-factory name="foo">,将name="foo"去掉即可

 

1.9        Hibernate核心类用法

1.9.1       使用Configuration装载配置

使用hibernate.cfg.xml,该文件中设置了数据库连接的属性和hbm.xml映射文件配置,Hibernate会自动加载该配置属性,并自动找到POJO类。

Configuration cfg=new Configuration();

Cfg.configure("hibernate.cfg.xml");

 

1.9.2       sessionFatcory

sessionFaction=cfg.buildSessionFactory();

 

1.9.3       Session

主要功能是提供对映射的实体类实例的创建、读取和删除操作。实例可能以下面3种状态存在。

自由状态(transient):不曾进行持久化,未与任何Session相关联

持久化状态(persistent):仅与一个Session相关联

游离状态(detached):已经进行过持久化,但当前未与任何Session相关联

 

1、  Save()保存对象

用于将一个新实例化的对象持久化,保存到数据库中

如:session.save(user);

 

2、  Load()装载对象

如果你知道某个实例的持久化标识,就可以使用Sessionload()方法来获取它。

如:User user=(User)session.load(User.class,new Integer("1"));

表示加载标识符为1User,并赋给一个新的实例变量user

此外,你可以把数据加载到指定的对象实例上(覆盖该实例原来的数据)

Session.load(user,new Integer("1"));(如果没有匹配的数据库记录,load方法可能抛出无法恢复的异常unrecoverable exception

 

3、  Get()装载对象

如果你不确定是否有匹配的行记录存在,应该使用get()方法,它会立刻访问数据库,如果没有,会返回null

 

4、  Flush()强制提交刷新

如果一个实例被更改了,则可以使用flush()将更改后的实例对象强制保存到数据库中。

 

5、  Update()提交游离状态的对象

 

6、  Delete()移除持久化对象

该函数用于从数据库中删除对象对应的记录

 

7、  Refresh()强制装载对象

任何时候都可以使用refresh()方法强迫装载对象和它的集合。如果你使用数据库触发器功能来处理对象的某些属性,这个方法就很有用了。

 

1.9.4       使用Transaction管理事务

Transaction tx=session.begionTransaction();

Tx.commit();

 

1.9.5       使用Query进行HQL查询

1、  不带参数的查询

Query query=session.createQuery(“from user”);

 

2、  带参数的查询

接口Query提供了对命名参数、JDBC风格的问号(?)参数两种参数绑定方法。

如:

Query query=session.createQuery("from User where username=:username");

query.setString("username","admin")

也可以使用集合型参数。如下所示,在SQL语句中使用in关键字指向一个命名参数列表

List names=new ArrayList();

names.add(admin);

names.add(test);

Query query=session.createQuery("from user where username in (:nameList)");

query.setParameterList("nameList",names);

 

3、  使用问号参数

Query query=session.createQuery("from user where username=?");

query.setString(0,"admin");

 

4、  取得List结果集

List list=query.list();

 

5、  取得迭代列表结果集

Iterate()

 

6、  取得一个对象

如果你知道当前查询只会返回一个对象,则可使用list()的快捷方式uniqueResult()来取得一个对象

User user=(User)query.uniqueResult()

 

7、  标量查询

查询可以在select从句中指定类的属性,甚至可以调用SQL统计函数

Iterator results=session.createQuery(

    "Select user.username,count(user.email) from user group by username")

    .list().iterator;

 

8、  分页查询

query.setFirstResult(10);//设置起始范围

query.setMaxResults(20);//设置结束范围

List list=query.list();

 

9、  创建SQL查询

可以使用createSQLQuery()方法,用普通的SQL来描述查询并由Hibernate处理将结果贪集转换成对象的工作。

List users=session.createSQLQuery(SELECT {user}.* FROM User {user}).list();

其中SQL别名需要用大括号包围起来。和Hibernate查询一样,SQL查询也可以包含命名参数和占位参数

 

1.9.6       使用Criteria进行条件查询

Criteria接口与Query接口非常类似,它允许你创建并执行面向对象的标准化查询。动态地使用面向对象API创建查询,而非在Java代码中嵌入字符串

创建Criteria实例

Cirteria criteria=session.createCriteria(User.class);

Criteria.setMaxResults(50);

List users=criteria.list();

 

1、  添加查询条件

查询条件是通过org.hibernate.criterion.Restrictions类来实现的,用来模拟SQL语句中的条件关键字,例如likebetweenandor

Criteria criteria=session.createCriteria(User.class);

criteria.add(Restrictions.like("username","admin%"));

criteria.add(Restrictions.between("ID",1,10));

List users=criteria.list();

 

2、  添加排序条件

可以使用org.hibernate.criterion.Order来为查询结果排序,它共包含两个方法,asc()desc(),分别实现SQL语句中的ascdesc关键字。通过调用CriteriaaddOrder()来添加多个Order实例,如下

List users=session.createCriteria(User.class)

.add(Restrictions.like("username","admin%"))

.addOrder(Order.asc("username"))

.addOrder(Order.asc("password"))

.list();

 

3、  示例查询

Org.hibernate.criterion.Example类允许通过一个给定实例来构建一个条件查询。

User user=new User();

User.setUsername();

List results=session.createCriteria(User.class)

    .add(Example.create(user)).list();

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值