`
zisefeiniao
  • 浏览: 171228 次
  • 性别: Icon_minigender_2
  • 来自: 成都
社区版块
存档分类
最新评论
阅读更多
今天开始学习Hibernate了,从完整的介绍、开发,也非常明白了Hibernate的作用是什么,而且使用这个Hibernate操作起来也很容易的
一、Struts与Hibernate
Struts是用来替代Servlet,可以在JSP上使用标签来减少scriplet代码,完成跳转控制等。
Hibernate等后台框架主要完成后台的数据库操作的封装,Hibernate等完成类似功能的框架,其共同的实现原理为ORMapping(ORMapping概念最早是由EJB2.0提出的)。

二、各种操作数据库方式的方案比较

SQL/JDBC:之前的DAO开发一直使用的JDBC,优点和缺点都很明显,最大的优点是性能比较高。
EntityBean:优点:在2.0中第一个提出ORMapping,3.0中结合了Hibernate的优点,简化配置,使开发代码更容易。 缺点:没有真分页,如果要使用真分页,需要手工编写sql语句

JDO:优点:可以直接通过对类的操作影响到数据库。缺点:执行性能过低,设计上有问题。
ApacheOJB:没有可以使用的学习文档,而且需要其他框架的支持。

iBATIS:在Hibernate之前最完善的ORMapping框架,可以对数据库的操作进行比较完善的封装。但还需要通过编写sql语句进行操作(SQL语句需要在xml配置文件中保存)。

Hibernate:现在使用的最好的ORMapping框架,对于多表的关联查询支持很好,可以通过很简单的代码完成两表乃至多表的关联查询。缺点:性能是所有框架中最低。


Hibernate的使用

一、建立数据库
数据库脚本
DROP DATABASE mldn_hibernate;

CREATE DATABASE mldn_hibernate;

USE mldn_hibernate;

DROP TABLE testtb ;

CREATE TABLE testtb (
id int primary key auto_increment ,
title varchar(20) not null,
post_date datetime not null,
page int not null,
price double not null
);


二、建立项目并加入支持


1、建立项目


2、通过MyEclipse配置数据库连接
注意,在加入Hibernate框架支持的时候有这步操作,可以通过那个手工配置,但比较麻烦,所以一般先通过MyEclipse配置好数据库连接,然后在那里简单修改。
(1)选择菜单中的window  show view  other

(2)选择MyEclips Enterprise WorkbenchDB Browser, 打开DB Browser

  


(3)在打开的DBBrowser中,点鼠标右键,选择New…

(4)配置数据库连接



(5)检查是否配置成功


如果该连接下面,显示了所有的数据库,则表示配置成功

3、加入Hibernate框架支持
(1)在项目上单击右键—>MyEclipse Add Hibernate Capabilities…


(2)选择版本及加入支持jar包

两种加入jar包的方式,第一种(Eclipse加入jar包的方式即为该方式),即一开始并没有真正加入jar包,等项目部署编译后,才真正加入,这样不方便做了项目去客户那儿演示,还得现在自己这儿部署,然后还要考虑把jar包带着等等;第二种方式,即把jar包直接拷贝到项目的/WebRoot/WEB-INF/lib下,拷走项目,jar包带着走。
(3)创建Hibernate核心配置文件,一般按照默认


(4)配置数据库连接
注意:如果之前没有通过MyEclipse进行过数据库连接配置,这儿的DB Driver下拉列表中就没有可选择的连接,那么所有配置需要手工填写,如下图




(5)是否创建SessionFactory类


一般不使用它创建,自己创建,所以取消选择

(6)加入了支持后,自动打开hibernate.cfg.xml,在此处,hibernate提供了可视化操作界面,可以在此处修改数据库连接配置

三、后台代码编写
1、编写pojo类(即vo类)(注意生成的映射配置文件)
vo的三个名称:
vo=Value Object值对象,用来保存数据库中值的对象。
to=Transfer Object传输对象,在EJB中vo对象被称为to,该对象需要实现序列化接口
pojo=Plain Old Java Object:经典Java对象,就是vo对象。
在EJB中vo又有另一个名称。

在Hibernate中可以自动生成pojo对象:
(1)在DBBrowser窗口中,选择要生成pojo的表,在表上点鼠标右键  Hibernate Reverse Engineering…

(2)配置映射关系(不要加入抽象类和DAO生成)

选择保存的文件夹


(3)选择主键生成方式
选择主键生成方式,这里要参考数据库本身表的主键方式,一般有以下几种选择
native:表示由数据库表自行处理,在mysql和sqlserver 数据库中,如果主键设置了自动增长,需要使用该方式
sequence:表示使用序列进行生成,在oracle数据库中如果需要自动增长,则使用该方式。
assigened:表示由pojo中填写的内容决定,除了以上情况以外,一般都使用该方式。


(4)在这里可以对单独的一个字段或表进行特殊处理,一般不会进行配置。


(5)询问是否以hibernate模式代开映射文件(单击no)

(6)查看自动生成的pojo类
package mldn.lin.pojo;

import java.util.Date;

/**
* Testtb generated by MyEclipse Persistence Tools
*/

public class Testtb implements java.io.Serializable {

// Fields

private Integer id;

private String title;

private Date postDate;

private Integer page;

private Double price;

// Constructors

/** default constructor */
public Testtb() {
}

/** full constructor */
public Testtb(String title, Date postDate, Integer page, Double price) {
this.title = title;
this.postDate = postDate;
this.page = page;
this.price = price;
}

// Property accessors

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getTitle() {
return this.title;
}

public void setTitle(String title) {
this.title = title;
}

public Date getPostDate() {
return this.postDate;
}

public void setPostDate(Date postDate) {
this.postDate = postDate;
}

public Integer getPage() {
return this.page;
}

public void setPage(Integer page) {
this.page = page;
}

public Double getPrice() {
return this.price;
}

public void setPrice(Double price) {
this.price = price;
}

}

(7)查看该类与对应表的映射配置文件(一个表或者一个pojo类对应一个映射配置文件,即一个映射关系,对应一个映射配置文件)

<?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">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<!-- 表示mldn_hibernate数据库中的testtb表与Testtb类对应 -->
    <class name="mldn.lin.pojo.Testtb" table="testtb" catalog="mldn_hibernate">
    <!-- 表示类的id属性类型为Integer,并且与表的主键对应 -->
        <id name="id" type="java.lang.Integer">
        <!-- 表中的主键列名为id -->
            <column name="id" />
            <!-- 主键的生成方式为native  -->
            <generator class="native" />
        </id>
         <!--
        类中title属性类型为String,与表中title字段对应,title字段的最大长度为20,而且为非空
         -->
        <property name="title" type="java.lang.String">
            <column name="title" length="20" not-null="true" />
        </property>
        <!--
        类中的postDate属性为Date类型,与表中的post_date字段对应,最大长度为19(字段为DateTime类型yyyy-MM-dd HH:mm:ss),如果表字段类型为Date类型,则为10位
         -->
        <property name="postDate" type="java.util.Date">
            <column name="post_date" length="19" not-null="true" />
        </property>
        <!-- 类中的page属性为Integer类型,与表中的page字段对应 -->
        <property name="page" type="java.lang.Integer">
            <column name="page" not-null="true" />
        </property>
        <!-- 类中的price属性为Double类型,与表中的price字段对应,最大精度为22 -->
        <property name="price" type="java.lang.Double">
            <column name="price" precision="22" scale="0" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

2、编写数据库连接类HibernateSessionFactory

(1)建立数据库连接类
为了使缓存可以起作用,数据库连接类一般都使用单例设计。

补充:单例模式的饿汉与懒汉方式
(a)饿汉即不管你现在是不是使用,都new一个数据库连接类对象
// 饿汉式
private static HibernateSessionFactory instance = new HibernateSessionFactory();

(b)懒汉即当你使用的时候,再看存不存在,如果不存在该对象再new一个
public static HibernateSessionFactory getInstance() {
// 懒汉式
/*
* if (instance == null ) { instance = new HibernateSessionFactory(); }
*/
return instance;
}
一般采用饿汉式,因为懒汉式严格来说存在非线程安全问题,两个人同时创建(几率很小),再说也提高不了多少性能,所以采用饿汉式即可

(2)创建Session对象(相当于JDBC的Connection)
注意:创建org.hibernate.Session对象时,需要org.hibernate.SessionFactory类对象。
SessionFactory:用来创建Session连接,并可以保存二级缓存,因此一般开发中只创建一个该对象。该类的openSession()方法:创建一个session连接。
// SessionFactory对象只创建一次,因为二级缓存信息保存在该类中
// org.hibernate.cfg.Configuration类用来读取配置文件
// configure方法表示进行读取
// buildSessionFactory表示根据读取的配置文件信息创建一个SessionFactory
// 如果进行多次创建则缓存无效,而且效率很低

package mldn.lin.dbc;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateSessionFactory {
//饿汉式单例模式
private static HibernateSessionFactory instance=new HibernateSessionFactory();

private SessionFactory sf;//用来创建Session连接

private Session session;

//单例设计模式,构造方法私有化
private HibernateSessionFactory(){
// sessionFactory只创建一次,因为二级缓存信息保存在该类中
// org.hibernate.cfg.Configuration类用来读取配置文件
// configure方法表示进行读取
// buildSessionFactory表示根据读取的配置文件信息创建一个SessionFactory
// 如果进行多次创建则缓存无效,而且效率很低
sf = new Configuration().configure().buildSessionFactory();
}

//需要一个静态方法,获得该单例模式设计的类的对象的静态方法
public static HibernateSessionFactory getInstance() {
// 懒汉式
/*
* if (this.instance == null ) { this.instance = new HibernateSessionFactory(); }
*/
return instance;
}

//取得数据库连接
public Session getConnection() {
//判断时需要对"是否进行着连接"也要判断,如果没有连接,则需要重新创建session,相当于原来判断连接是否关闭,因为没有提供判断是否关闭连接的方法,所以采用这种方式
if (session == null || !session.isConnected()) {
// 通过SessionFactory创建一个连接
session = this.sf.openSession();
}
return this.session;
}

//关闭一个连接
public void close() {
if (session != null) {
this.session.close();
}
}

//定义提交方法,因为Hibernate默认不是自动提交
public void commit() {
if (session != null) {
session.beginTransaction().commit();
}
}

//定义回滚方法
public void rollback() {
if (session != null) {
session.beginTransaction().rollback();
}
}

}

3、建立DAO接口(没变)
package mldn.lin.dao;

import java.util.List;

import mldn.lin.pojo.Testtb;

public interface TesttbDAO {

public boolean doInsert(Testtb t) throws Exception;

public boolean doDelete(int id) throws Exception;

public boolean doUpdate(Testtb t) throws Exception;

public List<Testtb> doSelectAll(int cp, int ls) throws Exception;

public int getAllCount() throws Exception;

public Testtb findByPrimaryKey(int id) throws Exception;

}


4、建立实现类
package mldn.lin.dao.impl;

import java.util.List;

import mldn.lin.dao.TesttbDAO;
import mldn.lin.dbc.HibernateSessionFactory;
import mldn.lin.pojo.Testtb;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Expression;

public class TesttbDAOImpl implements TesttbDAO {

//获得数据库连接类HibernateSessionFactory的对象,以此类获得数据库连接Session对象
//相当于原来的private DataBaseConnection dbc;//用来获得Connection对象
private HibernateSessionFactory instance=HibernateSessionFactory.getInstance();

public boolean doInsert(Testtb t) throws Exception {
// TODO Auto-generated method stub
//Session对象的save()方法
this.instance.getConnection().save(t);
return false;
}

public boolean doDelete(int id) throws Exception {
// TODO Auto-generated method stub
//方法一:用Session对象的delete()方法
//该方法需要先根据主键查询出该对象,然后删除该对象
//Session方式需要先查询再删除,而且无法支持多条同时删除,因此效率比较低,一般不使用该方式,而使用HQL方式则没有这些问题
//this.instance.getConnection().delete(findByPrimaryKey(id));
//return true;

//方法二:用org.hibernate.Query对象HQL方式删除
//注意HQL语句中的没有表的名称及字段,是该表对应的pojo对象及属性,操作对象然后通过映射关系影响表
String hql="DELETE FROM Testtb WHERE id= ?";
Query q=this.instance.getConnection().createQuery(hql);
q.setInteger(0, id);
if(q.executeUpdate()>0){
return true;
}
return false;
}

public boolean doUpdate(Testtb t) throws Exception {
// TODO Auto-generated method stub
//方法一:用Session对象的update()方法
//this.instance.getConnection().update(t);
//return true;

//方法二:用org.hibernate.Query对象HQL方式修改
//Session方式修改修改全部属性,而HQL则修改自己编写HQL语句中的属性
//用于表的字段比较多,而该修改操作只修改表中的某个字段的值,这样效率高
String hql="UPDATE Testtb SET title =?,postDate=?,page=?,price=? WHERE id= ?";
Query q=this.instance.getConnection().createQuery(hql);
q.setString(0, t.getTitle());
q.setDate(1, t.getPostDate());
q.setInteger(2, t.getPage());
q.setDouble(3, t.getPrice());
q.setInteger(4, t.getId());
if(q.executeUpdate()>0){
return true;
}
return false;
}

public Testtb findByPrimaryKey(int id) throws Exception {
// TODO Auto-generated method stub
//方法一:用Session对象的get()方法,Session对象只能完成按主键查询
return (Testtb) this.instance.getConnection().get(Testtb.class, id);

//方法二:用org.hibernate.Query对象HQL方式完成按主键查询
// String hql="FROM Testbb WHERE id=?";
// //或者String hql = "SELECT tb FROM Testtb AS tb WHERE id=?";
// Query q=this.instance.getConnection().createQuery(hql);
// q.setInteger(0, id);
// List all=q.list();
// if(all!=null && all.size()>0){
// return (Testtb) all.get(0);
// }


//方法三:用org.hibernate.Criteria对象的
// Criteria c=this.instance.getConnection().createCriteria(Testtb.class);
// //用org.hibernate.criterion.Expression加入查询条件
// c.add(Expression.eq("id", id));
// List all=c.list();
// if(all!=null && all.size()>0){
// return (Testtb) all.get(0);
// }
}

public List<Testtb> doSelectAll(int cp, int ls,String keyword) throws Exception {
// TODO Auto-generated method stub
//方法一:Criteria方式查询
Criteria c = this.instance.getConnection().createCriteria(Testtb.class);
c.setFirstResult((cp - 1) * ls);//设置查询的开始记录数
c.setMaxResults(ls);//设置查询返回的记录数量
c.add(Expression.like("title", "%"+keyword+"%"));

return (List<Testtb>)c.list();

// //方法二:Query方式查询
// String hql="SELECT tb FROM Testtb AS tb WHERE tb.title LIKE ?";
// //String hql="FROM Testtb AS tb WHERE tb.title LIKE ?";
// ////String hql="FROM Testtb WHERE title LIKE ?";
// Query q=this.instance.getConnection().createQuery(hql);
// q.setFirstResult((cp-1)*ls);//设置查询的开始记录数
// q.setMaxResults(ls);//设置查询返回的记录数量
// q.setString(0, "%"+keyword+"%");
//
// return (List<Testtb>)q.list();

//设置参数还有一种方式:使用":"作为参数标志
// String hql = "FROM Testtb AS tb WHERE tb.title LIKE :titleKeyword";
// Query q = this.instance.getConnection().createQuery(hql);
// // 设置查询参数
// q.setString("titleKeyword", "%"+keyword+"%");
}

public int getAllCount(String keyword) throws Exception {
// TODO Auto-generated method stub
//包含数据库函数的只能用Query对象方式进行查询
String hql="SELECT count(*) FROM Testtb";
Query q = this.instance.getConnection().createQuery(hql);
List all = q.list();
if (all != null && all.size() > 0) {
return (Integer) all.get(0);
}
return 0;
}

}


5、建立代理类(注意增、删、该的时候手工提交)
package mldn.lin.dao.proxy;

import java.util.List;

import mldn.lin.dao.TesttbDAO;
import mldn.lin.dao.impl.TesttbDAOImpl;
import mldn.lin.dbc.HibernateSessionFactory;
import mldn.lin.pojo.Testtb;

public class TesttbDAOProxy implements TesttbDAO {

private HibernateSessionFactory instance=HibernateSessionFactory.getInstance();

private TesttbDAO testtbdao;

public TesttbDAOProxy(){
this.testtbdao=new TesttbDAOImpl();
}

public boolean doInsert(Testtb t) throws Exception {
// TODO Auto-generated method stub
boolean flag=false;
try {
flag=this.testtbdao.doInsert(t);
this.instance.commit();
} catch (RuntimeException e) {
// TODO Auto-generated catch block
this.instance.rollback();
e.printStackTrace();
}finally{
this.instance.close();
}
return flag;
}

public boolean doDelete(int id) throws Exception {
// TODO Auto-generated method stub
boolean flag=false;
try {
flag=this.testtbdao.doDelete(id);
this.instance.commit();
} catch (RuntimeException e) {
// TODO Auto-generated catch block
this.instance.rollback();
e.printStackTrace();
}finally{
this.instance.close();
}
return flag;
}

public boolean doUpdate(Testtb t) throws Exception {
// TODO Auto-generated method stub
boolean flag=false;
try {
flag=this.testtbdao.doUpdate(t);
this.instance.commit();
} catch (RuntimeException e) {
// TODO Auto-generated catch block
this.instance.rollback();
e.printStackTrace();
}finally{
this.instance.close();
}
return flag;
}

public List<Testtb> doSelectAll(int cp, int ls, String keyword)
throws Exception {
// TODO Auto-generated method stub
List<Testtb> all = null ;
try {
all = this.testtbdao.doSelectAll(cp, ls, keyword);
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
this.instance.close();
}
return all;
}


public Testtb findByPrimaryKey(int id) throws Exception {
// TODO Auto-generated method stub
Testtb testtb = null;
try {
testtb =this.testtbdao.findByPrimaryKey(id);
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
this.instance.close();
}
return testtb;
}

public int getAllCount(String keyword) throws Exception {
// TODO Auto-generated method stub
int count = 0 ;
try {
count = this.testtbdao.getAllCount(keyword);
} catch (RuntimeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
this.instance.close();
}
return count;
}
}


6、编写工厂类
package mldn.lin.factory;

import mldn.lin.dao.TesttbDAO;
import mldn.lin.dao.proxy.TesttbDAOProxy;

public class DAOFactory {
public static TesttbDAO getTesttbDAOInstance(){
return new TesttbDAOProxy();
}
}

四、编写测试类
package mldn.lin.util;

import java.util.Date;

import mldn.lin.factory.DAOFactory;
import mldn.lin.pojo.Testtb;

public class Test {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// 插入
Testtb t = new Testtb();
t.setTitle("测试");
t.setPostDate(new Date());
t.setPage(11);
t.setPrice(13.56);

try {
System.out.println(DAOFactory.getTesttbDAOInstance().doInsert(t));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

发现出现以下警告
log4j:WARN No appenders could be found for logger (org.hibernate.cfg.Environment).
log4j:WARN Please initialize the log4j system properly.


五、添加日志文件
为了去除后台打印的警告信息,可以将Hibernate开发包中提供的hibernate-3.2\etc \log4j.properties文件拷贝到项目的src下。之后会提示读取配置文件的操作。
17:23:51,765  INFO Environment:479 - Hibernate 3.1.3
17:23:51,781  INFO Environment:509 - hibernate.properties not found
17:23:51,796  INFO Environment:525 - using CGLIB reflection optimizer
17:23:51,796  INFO Environment:555 - using JDK 1.4 java.sql.Timestamp handling
17:23:51,843  INFO Configuration:1308 - configuring from resource: /hibernate.cfg.xml
17:23:51,843  INFO Configuration:1285 - Configuration resource: /hibernate.cfg.xml
17:23:52,093  INFO Configuration:469 - Reading mappings from resource: mldn/lin/pojo/Testtb.hbm.xml
17:23:52,187  INFO HbmBinder:309 - Mapping class: mldn.lin.pojo.Testtb -> testtb
17:23:52,203  INFO Configuration:1419 - Configured SessionFactory: null
17:23:52,265  INFO DriverManagerConnectionProvider:41 - Using Hibernate built-in connection pool (not for production use!)
17:23:52,265  INFO DriverManagerConnectionProvider:42 - Hibernate connection pool size: 20
17:23:52,265  INFO DriverManagerConnectionProvider:45 - autocommit mode: false
17:23:52,281  INFO DriverManagerConnectionProvider:80 - using driver: com.mysql.jdbc.Driver at URL: jdbc:mysql://localhost:3306/mldn_hibernate
17:23:52,281  INFO DriverManagerConnectionProvider:86 - connection properties: {user=root, password=****}
17:23:52,484  INFO SettingsFactory:77 - RDBMS: MySQL, version: 5.0.22-community-nt
17:23:52,484  INFO SettingsFactory:78 - JDBC driver: MySQL-AB JDBC Driver, version: mysql-connector-java-5.0.4 ( $Date: 2006-10-19 17:47:48 +0200 (Thu, 19 Oct 2006) $, $Revision: 5908 $ )
17:23:52,515  INFO Dialect:103 - Using dialect: org.hibernate.dialect.MySQLDialect
17:23:52,515  INFO TransactionFactoryFactory:31 - Using default transaction strategy (direct JDBC transactions)
17:23:52,515  INFO TransactionManagerLookupFactory:33 - No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
17:23:52,515  INFO SettingsFactory:125 - Automatic flush during beforeCompletion(): disabled
17:23:52,515  INFO SettingsFactory:129 - Automatic session close at end of transaction: disabled
17:23:52,515  INFO SettingsFactory:136 - JDBC batch size: 15
17:23:52,515  INFO SettingsFactory:139 - JDBC batch updates for versioned data: disabled
17:23:52,515  INFO SettingsFactory:144 - Scrollable result sets: enabled
17:23:52,515  INFO SettingsFactory:152 - JDBC3 getGeneratedKeys(): enabled
17:23:52,515  INFO SettingsFactory:160 - Connection release mode: auto
17:23:52,515  INFO SettingsFactory:184 - Maximum outer join fetch depth: 2
17:23:52,515  INFO SettingsFactory:187 - Default batch fetch size: 1
17:23:52,515  INFO SettingsFactory:191 - Generate SQL with comments: disabled
17:23:52,515  INFO SettingsFactory:195 - Order SQL updates by primary key: disabled
17:23:52,515  INFO SettingsFactory:338 - Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
17:23:52,515  INFO ASTQueryTranslatorFactory:24 - Using ASTQueryTranslatorFactory
17:23:52,515  INFO SettingsFactory:203 - Query language substitutions: {}
17:23:52,515  INFO SettingsFactory:209 - Second-level cache: enabled
17:23:52,515  INFO SettingsFactory:213 - Query cache: disabled
17:23:52,515  INFO SettingsFactory:325 - Cache provider: org.hibernate.cache.EhCacheProvider
17:23:52,531  INFO SettingsFactory:228 - Optimize cache for minimal puts: disabled
17:23:52,531  INFO SettingsFactory:237 - Structured second-level cache entries: disabled
17:23:52,531  INFO SettingsFactory:257 - Echoing all SQL to stdout
17:23:52,531  INFO SettingsFactory:264 - Statistics: disabled
17:23:52,531  INFO SettingsFactory:268 - Deleted entity synthetic identifier rollback: disabled
17:23:52,531  INFO SettingsFactory:283 - Default entity-mode: pojo
17:23:52,562  INFO SessionFactoryImpl:154 - building session factory
17:23:52,578  WARN Configurator:126 - No configuration found. Configuring ehcache from ehcache-failsafe.xml found in the classpath: jar:file:/F:/myEclips_workspace/hibernateDemo01/WebRoot/WEB-INF/lib/ehcache-1.1.jar!/ehcache-failsafe.xml
17:23:52,875  INFO SessionFactoryObjectFactory:82 - Not binding factory to JNDI, no JNDI name configured

六、show_sql
如果需要在后台执行时打印sql语句,可以在hibernate.cfg.xml中配置一个show_sql属性




通过设置该属性可以完成显示sql的功能
Hibernate: insert into mldn_hibernate.testtb (title, post_date, page, price) values (?, ?, ?, ?)


Hibernate常用API
一、org.hibernate.cfg.Configuration 类
在编写dbc时用
在创建SessionFactory.对象时用
private SessionFactory sf;
sf = new Configuration().configure().buildSessionFactory();
Configuration:配置类,用来读取hibernate.cfg.xml中的配置信息。
configure()方法:用来读取默认目录下的hibernate.cfg.xml文件
如果文件不在默认目录下且名称已经改变,则可以通过configure()的重载方法,传入该文件进行配置的读取

二、org.hibernate.SessionFactory类
在编写dbc时用
SessionFactory:用来创建Session连接,并可以保存二级缓存,因此一般开发中只创建一个该对象。
openSession():创建一个session连接,即打开一个Session连接。

package mldn.lin.dbc;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateSessionFactory {
//饿汉式单例模式
private static HibernateSessionFactory instance=new HibernateSessionFactory();

private SessionFactory sf;//用来创建Session连接

private Session session;

//单例设计模式,构造方法私有化
private HibernateSessionFactory(){
// sessionFactory只创建一次,因为二级缓存信息保存在该类中
// org.hibernate.cfg.Configuration类用来读取配置文件
// configure方法表示进行读取
// buildSessionFactory表示根据读取的配置文件信息创建一个SessionFactory
// 如果进行多次创建则缓存无效,而且效率很低
sf = new Configuration().configure().buildSessionFactory();
}

//需要一个静态方法,获得该单例模式设计的类的对象的静态方法
public static HibernateSessionFactory getInstance() {
// 懒汉式
/*
* if (this.instance == null ) { this.instance = new HibernateSessionFactory(); }
*/
return instance;
}
//取得数据库连接
public Session getConnection() {
//判断时需要对"是否进行着连接"也要判断,如果没有连接,则需要重新创建session,相当于原来判断连接是否关闭,因为没有提供判断是否关闭连接的方法,所以采用这种方式
if (session == null || !session.isConnected()) {
// 通过SessionFactory创建一个连接
session = this.sf.openSession();
}
return this.session;
}
//关闭一个连接
public void close() {
if (session != null) {
this.session.close();
}
}
//定义提交方法,因为Hibernate默认不是自动提交
public void commit() {
if (session != null) {
session.beginTransaction().commit();
}
}
//定义回滚方法
public void rollback() {
if (session != null) {
session.beginTransaction().rollback();
}
}
}


三、org.hibernate.Session类
Session:相当于一个Connection连接对象,并封装了一定的数据库操作方法
close():关闭当前数据库连接
beginTransaction:打开一个事务操作,可以返回一个Transaction对象
isConnected():判断当前是否连接着数据库

四、org.hibernate.Transaction
commit():提交事务
rollback():回滚事务

五、数据库CRUD操作涉及的类
1、Session类
(1)save():数据库的添加记录操作只能通过Session对象的save()方法实现
(2)delete():删除一个对象所对应的记录,传入要删除的对象
使用该方法的时候一般都是先按主键查询出要删除的对象,然后删除
public boolean doDelete(int id) throws Exception {
// TODO Auto-generated method stub
//方法一:用Session对象的delete()方法
//该方法需要先根据主键查询出该对象,然后删除该对象
//Session方式需要先查询再删除,而且无法支持多条同时删除,因此效率比较低,一般不使用该方式,而使用HQL方式则没有这些问题
this.instance.getConnection().delete(findByPrimaryKey(id));
return true;
}
(3)update():修改一个对象所对应的记录
saveOrUpdate():进行修改或插入操作,根据该数据是否存在进行判断,如果存在则执行修改方法,如果不存在,则执行插入。
public boolean doUpdate(Testtb t) throws Exception {
// TODO Auto-generated method stub
//方法一:用Session对象的update()方法
this.instance.getConnection().update(t);
return true;
}
Session方式修改修改全部属性,而HQL则修改自己编写HQL语句中的属性
(4)查询
通过Session对象只能实现按主键查询
public Testtb findByPrimaryKey(int id) throws Exception {
// TODO Auto-generated method stub
//方法一:用Session对象的get()方法,Session对象只能完成按主键查询
return (Testtb) this.instance.getConnection().get(Testtb.class, id);
//load()方法和get()方法功能一样,区别
// get():根据主键值查询一条记录,需要传入要查询对象的类型(class)和主键值,如果没有查询到则返回null值
// load():根据主键值查询一条记录,需要传入要查询对象的类型(class)和主键值,如果没有查询到则抛出异常。
//return (Testtb) this.instance.getConnection().load(Testtb.class, id);}

(5)如果要实现其他查询,需要借助Criteria和Query类

而这两个类的对象可以通过Session对象的createCriteria()和createQuery()方法得到

2、Query
(1)Query对象直接通过编写HQL语句,完成数据库RUD操作。
(2)Query不支持插入功能。
(3)在HQL中可以使用数据库函数
(4)分页查询条件
a、setFirstResult():设置查询的开始记录数,用来分页
b、setMaxResults():设置查询返回的记录数量,用来分页
(5)设置HQL语句的参数,两种方式
a、使用?作为参数标志
String hql = "FROM Testtb AS tb WHERE tb.title LIKE ?";
Query q = this.instance.getConnection().createQuery(hql);
// 设置查询参数
q.setString(0, "%测%");

b、使用“:”作为参数标志
String hql = "FROM Testtb AS tb WHERE tb.title LIKE :keyword";
Query q = this.instance.getConnection().createQuery(hql);
// 设置查询参数
q.setString("keyword", "%测%");
使用:需要在 :后加入参数的名称,在进行设置时,根据名称为参数设置值

(6)list():返回查询结果,是个集合
(7)注意:
HQL语句中的没有表的名称及字段,是该表对应的pojo对象及属性,操作对象然后通过映射关系影响表,
和SQL语句的区别:
原来写表名的地方,现在用pojo对象;
原来写字段的地方,现在写pojo对象的属性;
其他相同(不用LIMIT、ROWNUM等了);

(8)完成删除功能
public boolean doDelete(int id) throws Exception {
// TODO Auto-generated method stub
//方法一:用Session对象的delete()方法
//该方法需要先根据主键查询出该对象,然后删除该对象
//Session方式需要先查询再删除,而且无法支持多条同时删除,因此效率比较低,一般不使用该方式,而使用HQL方式则没有这些问题
// this.instance.getConnection().delete(findByPrimaryKey(id));
// return true;

//方法二:用org.hibernate.Query对象HQL方式删除
String hql="DELETE FROM Testtb WHERE id= ?";
Query q=this.instance.getConnection().createQuery(hql);
q.setInteger(0, id);
if(q.executeUpdate()>0){
return true;
}
return false;
}
(9)完成修改操作
public boolean doUpdate(Testtb t) throws Exception {
// TODO Auto-generated method stub
//方法一:用Session对象的update()方法
// this.instance.getConnection().update(t);
// return true;

//方法二:用org.hibernate.Query对象HQL方式修改
//Session方式修改修改全部属性,而HQL则修改自己编写HQL语句中的属性
//当表的字段比较多,而该修改操作只修改表中的某个字段的值,HQL方式这样效率高
String hql="UPDATE Testtb SET title =?,postDate=?,page=?,price=? WHERE id= ?";
Query q=this.instance.getConnection().createQuery(hql);
q.setString(0, t.getTitle());
q.setDate(1, t.getPostDate());
q.setInteger(2, t.getPage());
q.setDouble(3, t.getPrice());
q.setInteger(4, t.getId());
if(q.executeUpdate()>0){
return true;
}
return false;
}

(10)完成查询功能
○1当查询结果需要返回对象时,直接用该类的List集合接收即可
a、当查询结果需要返回对象时,可以不写SELECT,直接使用FROM 类名的形式,这样通过list方法返回的集合中保存的数据类型为该类的对象类型。

String hql = "FROM Testtb";

b、如果编写SELECT也需要返回对象,可以将类定义一个别名,在SELECT后加入该别名,表示查询的是类而不是类中的某一个属性

String hql = "SELECT tb FROM Testtb AS tb";

○2如果与SQL相同,只查询其中的某一个或多个字段(属性),返回结果需要使用其他方式保存。
a、当查询一个属性时,返回的集合中的元素类型为该属性类型,那么用来属性类型的集合接收即可
b、如果查询结果为多个属性,则返回的集合中的元素是对象的数组,该数组的类型为Object类型,该对象中包含了当前记录查询出的所有属性,可以将这些属性通过循环组织成为一个对象。那么需要用Object类型的集合接收。
public List<Testtb> findAll(int cp, int ls) throws Exception {
// TODO Auto-generated method stub
String hql = "SELECT tb.id,tb.page,tb.title,tb.postDate FROM Testtb AS tb";
Query q = this.instance.getConnection().createQuery(hql);
// 分页
q.setFirstResult((cp - 1) * ls);
q.setMaxResults(ls);
List all = q.list();
Iterator iter = all.iterator();
List returnValue = null;
while (iter.hasNext()) {
Object[] obj = (Object[]) iter.next();
if (returnValue == null) {
returnValue = new ArrayList();
}
Testtb tb = new Testtb();
tb.setId((Integer) obj[0]);
tb.setPage((Integer) obj[1]);
tb.setTitle((String) obj[2]);
tb.setPostDate((Date) obj[3]);

returnValue.add(tb);
}

return returnValue;
}

(11)Query对象也支持SQL方式进行查询,一般不使用。
如果使用SQL语句进行查询,则返回的集合中的数据类型为Object数组或单个属性的类型。
Query q=this.instance.getConnection().createSQLQuery(sql);

(12)如果要求开发过程中,在java代码中不出现任何的QL语句(SQL和HQL),可以将语句配置到映射文件中,针对哪个类进行的操作就需要配置到哪个类的映射文件中。
例如:在Testtb.hbm.xml中加入一个查询全部的HQL
    <class name="org.liky.pojo.Testtb" table="testtb" catalog="testdb">
        <id name="id" type="java.lang.Integer">
            <column name="id" />
            <generator class="native" />
        </id>
        <property name="title" type="java.lang.String">
            <column name="title" length="20" not-null="true" />
        </property>
        <property name="postDate" type="java.util.Date">
            <column name="post_date" length="19" not-null="true" />
        </property>
        <property name="page" type="java.lang.Integer">
            <column name="page" not-null="true" />
        </property>
        <property name="price" type="java.lang.Double">
            <column name="price" precision="22" scale="0" not-null="true" />
        </property>
    </class>
    <query name="queryAll">
     FROM Testtb AS tb WHERE tb.title LIKE ?
    </query>
在实现类中通过getNamedQuery方法调用该查询语句:
Query q = this.instance.getConnection().getNamedQuery("queryAll");
// 设置查询参数
q.setString(0, "%测%");

3、Criteria
(1)Criteria对象直接通过编写Java代码拼成SQL语句。
(2)Criteria只支持查询,不支持修改与删除功能。
(3)在Criteria查询时无法使用数据库函数
(4)查询条件
a、setFirstResult():设置查询的开始记录数,用来分页
b、setMaxResults():设置查询返回的记录数量,用来分页
c、在使用Criteria查询时,如果要使用查询条件,需要使用Expression类对条件进行拼接
Criteria c = this.instance.getConnection().createCriteria(Testtb.class);
// 加入查询条件
// SQL : .... testtb WHERE id = 1
c.add(Expression.eq("id", 1));
Map m = new HashMap();
m.put("id", 1);
m.put("title", "测试");
c.add(Expression.allEq(m));
// SQL : .... testtb WHERE id IN (1,3,5,7) AND (id > 2 OR
// title LIKE '%测试%' and price < 20)
c.add(Expression.and(Expression.in("id", ids), Expression.or(Expression
.gt("id", 2), Expression.and(Expression.like("title", "%测试%"),
Expression.lt("price", 20.0)))));

d、在使用Criteria查询时,使用Example类来定义范例,可以按照范例进行查询
Testtb tb = new Testtb();
tb.setPage(11);
tb.setTitle("测试");

c.add(Example.create(tb));

(5)list():返回查询结果,是个集合


4、Expression
在使用Criteria查询时,如果要使用查询条件,需要使用Expression类对条件进行拼接
(1)等于
c.add(Expression.eq("id", 1));
(2)多个相等条件
allEq方法,将一个Map中的Key与Value全部拼写为相等的判断条件
Map m = new HashMap();
m.put("id", 1);
m.put("title", "测试");
c.add(Expression.allEq(m));
(3)比较大小:gt、lt、ge、le
c.add(Expression.gt("page", 10));
(4)判断属性是否在某一个范围内:between
c.add(Expression.between("page", 10, 20));
(5)模糊查询:like
c.add(Expression.like("title", "%测%"));
(6)处理IN关键字查询:in
Integer[] ids = {1,3,5,7};
c.add(Expression.in("id", ids));
(7)对两个属性之间进行比较操作:eqProperty,gtProperty等
// SQL : .... testtb WHERE id < page
c.add(Expression.ltProperty("id", "page"));
(8)对多个条件进行联合查询:and、or
// SQL : .... testtb WHERE id IN (1,3,5,7) AND (id > 2 OR
// title LIKE '%测试%' and price < 20)
c.add(Expression.and(Expression.in("id", ids), Expression.or(Expression
.gt("id", 2), Expression.and(Expression.like("title", "%测试%"),
Expression.lt("price", 20.0)))));


5、Example
在使用Criteria查询时,使用Example类来定义范例,所有符合该条件的记录都会被查询出来
Testtb tb = new Testtb();
tb.setPage(11);
tb.setTitle("测试");

c.add(Example.create(tb));
根据提供的样例进行查询,将样例对象中的除主键以外的非空属性都作为查询条件拼入到sql中。
分享到:
评论

相关推荐

    Hibernate 基础.ppt

    【Hibernate 基础】是Java开发中一个重要的部分,主要关注如何将对象模型与关系数据库进行映射,以简化数据库操作。本PPT由传智播客制作,旨在帮助学习者掌握Hibernate的基础知识和应用。 首先,我们需要理解基于B/...

    hibernate基础jar包

    hibernate基础jar包。包含junit,antlr,don4j,hibernate-commons-annotations,hibernate-core,hibernate-jpa-api,javassit,jboss-logging,jboss-transaction-api

    HIbernate基础包

    在本"Hibernate基础包"中,包含了用于SSH开发所需的全部核心库,使得开发者能够快速搭建项目并进行数据库交互。 首先,Hibernate的核心功能在于它的ORM(对象关系映射)机制。ORM允许开发者通过Java对象来操作...

    Hibernate基础jar包

    本篇文章将深入探讨`Hibernate基础jar包`的构成,以及它们在Java Hibernate框架中的作用。 首先,Hibernate的核心jar包是实现ORM功能的基础。这些jar包包括但不限于以下: 1. **hibernate-core.jar**:这是...

    Hibernate基础教程Hibernate基础教程

    **Hibernate基础教程** Hibernate是一个强大的Java对象关系映射(ORM)框架,它简化了数据库操作,使得开发人员能够以面向对象的方式处理数据。本教程将深入探讨Hibernate的基础知识,包括安装配置、实体类定义、...

    Hibernate基础学习源码

    本资源“Hibernate基础学习源码”提供了五个不同阶段的学习示例,分别命名为Hibernate_01至Hibernate_04以及Hibernate_M2M,涵盖了Hibernate的基本概念、配置、实体映射、CRUD操作以及多对多关系的处理。 1. **...

    hibernate基础 入门/ hibernate basic

    ### Hibernate基础知识点详解 #### 一、什么是对象关系映射(ORM)以及为什么使用ORM? 在企业级应用开发中,持久层(persistence layer)占据了非常重要的地位。它主要负责处理与数据库之间的交互,包括数据的...

    springboot+hibernate基础项目

    在本项目中,"springboot+hibernate基础项目"是一个使用Spring Boot和Hibernate框架构建的典型Java Web应用。Spring Boot简化了Spring的配置过程,而Hibernate则是一个强大的ORM(对象关系映射)工具,使得数据库...

    hibernate 基础jar包和mysql程序驱动

    **Hibernate基础知识** 1. **什么是Hibernate**:Hibernate是一个开源的Java ORM框架,它简化了Java应用与关系数据库之间的交互。通过提供一套API,Hibernate可以将Java对象自动持久化到关系数据库中,反之亦然,...

    Hibernate基础全攻略

    **Hibernate基础全攻略** Hibernate,一个强大的Java对象关系映射(ORM)框架,极大地简化了数据库操作,使得开发者可以专注于业务逻辑而不是繁琐的SQL代码。本篇攻略将深入探讨Hibernate的基础知识,帮助初学者...

    hibernate基础教程.pdf

    **Hibernate 框架概述** Hibernate 是一个开源的对象关系映射(ORM)框架,它允许开发者用面向对象的方式来处理数据库操作。ORM 解决了在 Java 应用程序中使用传统 JDBC 进行数据库操作时遇到的繁琐代码问题,将...

    Hibernate基础架包

    这个“Hibernate基础架包”包含了进行Hibernate开发所需的基本库文件,使得开发者可以快速地将其集成到自己的项目中,无需手动配置大量的依赖。 在Hibernate中,核心概念包括: 1. **实体(Entities)**:实体代表...

    hibernate基础教程ppt加api文档

    **Hibernate基础教程** Hibernate是一个强大的Java对象关系映射(ORM)框架,它简化了数据库与Java应用程序之间的数据交互。这个基础教程将引导我们逐步了解Hibernate的核心概念和使用方法。 **一、Hibernate概述*...

    hibernate基础教程 配套代码包 Beginning Hibernate 有PDF教程配套

    《Hibernate基础教程》是针对Java开发人员的一本经典教材,主要涵盖了如何使用Hibernate这一流行的ORM(对象关系映射)框架来简化数据库操作。配套代码包"Bh3 2nd Ed Source Code"则提供了实例代码,帮助读者更好地...

Global site tag (gtag.js) - Google Analytics