首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Hibernate 简介 容易实例

2012-12-22 
Hibernate 简介 简单实例hibernate是什么?在实际的java开发过程中,我们要建立数据和维护数据以及进行数据

Hibernate 简介 简单实例

hibernate是什么?

在实际的java开发过程中,我们要建立数据和维护数据以及进行数据处理,比如删除某条数据,先是取得数据库连接,执行sql语句达到数据操作逻辑需要(如删除等于某ID的记录),释放连接等等,我们在这个过程中需要编写大量重复性且繁琐的代码。

?

为解决这个问题,hibernate应势而生,hibernate其实就是一个开发框架,它是一个开源的轻量级的O/R Mapping框架,O/R Mapping的意思大概就是对象(说的是数据吧)/关系 映射。这个在后面的例子中就会有体悟。其目标就是要把程序员从95%的常用数据持久化编码中解放出来,从而能够更多地关注于业务逻辑及其实现。Hibernate支持常用的多种数据库,只要简单配置就可以了。

?

Hibernate版本介绍

Hibernate较新的是3系列,它相对于2系统
更容易与持久化对象交互
提供强大的对象关系查询
完全事件驱动,支持java5,对游标和自定义类型支持
更高效的级联删除和支持列级延迟加载

?

Hibernate的应用方案

Hibernate可以看作是位于应用程序和数据库间的一个中间层,通过配置和映射信息为应用程序提供持久化对象及相关服务,有多种应用方案:
。应用层完全不关心数据库连接、事务等令人烦恼的东西,完全交由Hibernate负责,通过Session获取持久化对象
。较轻的体系,忽略某些部分,直接操作JDBC、JTA,这都取决于应用的需要

?

1、准备工作

?

到www.hibernate.org上去下载Hibernate发布包,将他们放到ClassPath路径里面,把这些jar包作为外部包添加到Build Path,右击工程名-->Build Path-->add External archives,选择hibernate包就可以了用myeclipse加环境更简便。另外,安装好mysql数据库。

?

2、持久化类及其映射文件

文章类 Article.java

package beans;import java.util.HashSet;import java.util.Set;public class Article {    private Long id;    private Column refColumn;    private String name;        private Set<Author> authors;    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Column getRefColumn() {        return refColumn;    }    public void setRefColumn(Column refColumn) {        this.refColumn = refColumn;    }    // one article may be wirtten by a few persons    public Set<Author> getAuthors() {        if (authors == null)            authors = new HashSet<Author>();        return this.authors;    }    public void setAuthors(Set<Author> authors) {        this.authors = authors;    }}
?

文章类映射文件 Article.hbm.xml:

?

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="beans.Article" table="tb_articles">        <id name="id" column="article_id" type="java.lang.Long">            <generator />        </id>        <property name="name" type="string">            <column name="article_name" length="100" not-null="true" />        </property>        <!--'ref' is the field name in tb_articles, which refer to column_id of tb_columns -->        <many-to-one name="refColumn" column="ref" not-null="true" />        <!-- inverse="true" mean a author refers to many artilces -->        <set name="authors" table="tb_articles_author" inverse="true"            order-by="author_id">            <!-- means an article could be refered to more than one author values -->            <key column="article_id" not-null="true" />            <many-to-many column="author_id" />        </set>    </class></hibernate-mapping>
?

作者类 Author.java

?

package beans;import java.util.HashSet;import java.util.Set;public class Author {    private Long id;    private String name;    private Set<Article> articles;    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Set<Article> getArticles() {        if (articles == null)            articles = new HashSet<Article>();        return this.articles;    }    public void setArticles(Set<Article> articles) {        this.articles = articles;    }}
?

作者类的映射文件 Author.hbm.xml

?

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="beans.Author" table="tb_authors">        <id name="id" column="id" type="java.lang.Long">            <generator />        </id>        <property name="name" type="string">            <column name="name" length="100" not-null="true" />        </property>        <!--             - 'inverse' value must be match value of Article.hbm.xml, means can not set as 'true' meanwhile.            (of course you can only set it in one file. )            - The side set as 'true'(at least a side must be 'true'), whose object could invoke setXXX(? extends Set),             the oppsite side will not impact even it invokes the method.                        Here 'false' means a author is corresponds to many articles.            (fileds of tb_articles_author are combined keys)        -->        <set name="articles" table="tb_articles_author" inverse="false"            order-by="article_id">            <!-- means a author id could be refered to more than one article values -->            <key column="author_id" not-null="true" />            <many-to-many column="article_id" />        </set>    </class></hibernate-mapping>
?

?

目录类 Column.java

?

package beans;import java.util.HashSet;import java.util.Set;public class Column {    private Long id;    private String name;    private Set<Article> articles;    public Long getId() {        return id;    }    public void setId(Long id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Set<Article> getArticles() {        if (articles == null)            articles = new HashSet<Article>();        return this.articles;    }    public void setArticles(Set<Article> articles) {        this.articles = articles;    }}
?

目录类的映射文件 Column.hbm.xml

?

<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping>    <class name="beans.Column" table="tb_columns">        <id name="id" column="column_id" type="java.lang.Long">            <generator />        </id>        <property name="name" type="string">            <column name="column_name" length="100" not-null="true" />        </property>        <!--             please note that 'inverse' value in many-to-many element of Article.hbm.xml, which can be set 'false'.          -->        <set name="articles" table="tb_articles" inverse="true"            order-by="article_id asc">            <!--                 'ref' is corresponding to the field of tb_aritcles,                 even it could be defined other name that different from the one defined in Article.hbm.xml,                 then one more field will be created            -->            <key column="ref" not-null="true" />            <one-to-many />        </set>    </class></hibernate-mapping>
?

3、辅助类
?
它的作用就是让Hibernate真正工作起来,并且封闭一下最基本的CRUD操作,就是删,增,修改等操作。

?

package util;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;public class HibernateUtil {    private static SessionFactory sessionFactory;    static {        try {            sessionFactory = new Configuration().configure()                    .buildSessionFactory();        } catch (Exception e) {            System.err.println("Error creating SessionFactory");            e.printStackTrace();        }    }    public static SessionFactory getSessionFactory() {        return sessionFactory;    }    public static Session getCurrentSession() {        return sessionFactory.getCurrentSession();    }}

?

当然,为了简单地去进行对象操作,还写个DAO(Data Access Object),可以将CRUD方法写在里面,当然这些方法体也可以不封装。

?

package dao;import org.hibernate.Session;import util.HibernateUtil;import beans.Article;public class ArticleDao {    public Article find(Long id) {        Session session = HibernateUtil.getCurrentSession();        Article article = (Article) session.load(Article.class, id);        return article;    }    public void save(Article article) {        Session session = HibernateUtil.getCurrentSession();        session.saveOrUpdate(article);    }    public void delete(Article article) {        Session session = HibernateUtil.getCurrentSession();        session.delete(article);    }}
?
package dao;import org.hibernate.Session;import util.HibernateUtil;import beans.Author;public class AuthorDao {    public Author find(Long id) {        Session session = HibernateUtil.getCurrentSession();        Author author = (Author) session.load(Author.class, id);        return author;    }    public void save(Author author) {        Session session = HibernateUtil.getCurrentSession();        session.saveOrUpdate(author);    }    public void delete(Author author) {        Session session = HibernateUtil.getCurrentSession();        session.delete(author);    }}
?
package dao;import org.hibernate.Session;import util.HibernateUtil;import beans.Column;public class ColumnDao {    public Column find(Long id) {        Session session = HibernateUtil.getCurrentSession();        Column column = (Column) session.load(Column.class, id);        return column;    }    public void save(Column column) {        Session session = HibernateUtil.getCurrentSession();        session.saveOrUpdate(column);    }    public void delete(Column column) {        Session session = HibernateUtil.getCurrentSession();        session.delete(column);    }}
?

4、配置Hibernate
?
它就是指定数据源等信息,文件名为hibernate.cfg.xml,放到classpath的根目录下。(其实还有另种方法),下面是针对Mysql数据库的配置,数据库的配置在Hibernate包里有说明:

?

<?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="connection.username">root</property>        <property name="connection.url">            jdbc:mysql://localhost:3306/test        </property>        <property name="dialect">            org.hibernate.dialect.MySQLDialect        </property>        <property name="connection.password">root</property>        <property name="current_session_context_class">thread</property>        <property name="connection.driver_class">            com.mysql.jdbc.Driver        </property>        <property name="hbm2ddl.auto">create</property>        <mapping resource="beans/Author.hbm.xml" />        <mapping resource="beans/Column.hbm.xml" />        <mapping resource="beans/Article.hbm.xml" />    </session-factory></hibernate-configuration>

?

dialect 属性指定Hibernate应该生成什么样的SQL与数据库交互,hbm2ddl.auto属性告诉Hibernate自动为我们生成数据库sample,如果为create-drop则会自动删除,在DAO中没有关闭session,current_session_context_class属性的值是thread,Hibernate创建session时将其绑定到当前线程,事务结束后自动剥离并关闭,下次调用get方法产生新的,所以应该配合事务一起使用

?

5、看效果

?

写一个测试类,它用到了 log4j,log4j能格式化一些输出,能看出哪些日志是一段的(时间戳),以及调节日志级别等。

?

package test;import java.util.Set;import org.apache.log4j.Logger;import org.apache.log4j.PropertyConfigurator;import org.hibernate.Session;import util.HibernateUtil;import beans.Article;import beans.Author;import beans.Column;import dao.ArticleDao;import dao.AuthorDao;import dao.ColumnDao;public class DemoRunner {    static Logger logger = Logger.getLogger(DemoRunner.class.getName());    private AuthorDao authorDao = new AuthorDao();    private ColumnDao columnDao = new ColumnDao();    private ArticleDao articleDao = new ArticleDao();    public DemoRunner() {        initDB();    }    public static void main(String[] args) {        PropertyConfigurator.configure("DemoRunner.properties");        new DemoRunner().showInfo();    }    /**     * get article informaion and update author info     *      */    public void showInfo() {        Column column;        Set<Article> articles;        Author author;        Session session = HibernateUtil.getCurrentSession();        try {            session.beginTransaction();            column = columnDao.find(1L);            logger.warn("find column information: id = " + column.getId()                    + ", name = " + column.getName());            articles = column.getArticles();            author = authorDao.find(1L);            for (Article article : articles) {                logger.warn("it has article -> aritlce id: " + article.getId()                        + ", article name: " + article.getName()                        + ", artilce author id: "                        + article.getAuthors().iterator().next().getId());                // add articles that written by author 2 to author whose id is 1                author.getArticles().add(article);            }            // delete all articles of author whose id is 2            authorDao.delete(authorDao.find(2L));            logger                    .warn("author whose id is 2 has been deleted, also whose articles...");            session.getTransaction().commit();        } catch (Exception e) {            session.getTransaction().rollback();        }        // reopen and scan to verify the articles of author 1 now.        session = HibernateUtil.getSessionFactory().openSession();        column = (Column) session.load(Column.class, 1L);        articles = column.getArticles();        for (Article article : articles) {            logger.warn("article of author whose id is 1 >> article id: "                    + article.getId() + ", name: " + article.getName());        }        session.close();    }    public void initDB() {        Author author;        Column column;        Article article;        Session session = HibernateUtil.getCurrentSession();        try {            session.beginTransaction();            java.util.Set<Author> setOfAuthor = new java.util.HashSet<Author>();            java.util.Set<Column> setOfColumn = new java.util.HashSet<Column>();            java.util.Set<Article> setOfArticle = new java.util.HashSet<Article>();            // create author 1            author = new Author();            author.setName("Daniel");            authorDao.save(author);            logger.warn("Created a new author, [Id = " + author.getId()                    + ". Name = " + author.getName() + ". ]");            setOfAuthor.add(author);            // create author 2            author = new Author();            author.setName("David");            authorDao.save(author);            logger.warn("Created a new author, [Id = " + author.getId()                    + ". Name = " + author.getName() + ". ]");            setOfAuthor.add(author);            // create column 1            column = new Column();            column.setName("catelog.computer");            columnDao.save(column);            logger.warn("Created a new column, {Id = " + column.getId()                    + ". Name = " + column.getName() + ". }");            setOfColumn.add(column);            // create article 1            article = new Article();            article.setName("Think in java");            article.setRefColumn(column);            articleDao.save(article);            setOfArticle.add(article);            logger.warn("aticle [" + article.getName() + "] added to -> "                    + column.getName());            // create article 2            article = new Article();            article.setName("Getting started Jboss");            article.setRefColumn(column);            articleDao.save(article);            setOfArticle.add(article);            logger.warn("aticle [" + article.getName() + "] added to -> "                    + column.getName());            // create column 2            column = new Column();            column.setName("catelog.Math");            columnDao.save(column);            logger.warn("Created a new column, {Id = " + column.getId()                    + ". Name = " + column.getName() + ". }");            setOfColumn.add(column);            // create article 3            article = new Article();            article.setName("middle school of math");            article.setRefColumn(column);            articleDao.save(article);            setOfArticle.add(article);            logger.warn("aticle [" + article.getName() + "] added to -> "                    + column.getName());            // create article 4            article = new Article();            article.setName("math algorithm");            article.setRefColumn(column);            articleDao.save(article);            setOfArticle.add(article);            logger.warn("aticle [" + article.getName() + "] added to -> "                    + column.getName());            // column.setArticles(setOfArticle);            // article.setAuthors(setOfAuthor);            author.setArticles(setOfArticle);            logger.warn("4 articles are added to author 2!!");            session.getTransaction().commit();        } catch (Exception e) {            session.getTransaction().rollback();            e.printStackTrace();        }    }}
?

log4j是要有配置文件的:

?

log4j.rootLogger=WARN, A1log4j.appender.A1=org.apache.log4j.ConsoleAppenderlog4j.appender.A1.layout=org.apache.log4j.PatternLayout# It is a PatternLayout# %r means the time from begin. # %p means level# %t means thread# %c logger making the log request# %x nested diagnostic context (NDC)# -%m%n description informationlog4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %20c %3x - %m%n
?

最终文件的结构就是:

?

jar tf xxx.jarbeans/Column.javabeans/Article.javabeans/Author.javabeans/Article.hbm.xmlbeans/Author.hbm.xmlbeans/Column.hbm.xmldao/AuthorDao.javadao/ColumnDao.javadao/ArticleDao.javatest/DemoRunner.javautil/HibernateUtil.javaDemoRunner.propertieshibernate.cfg.xml
?

运行的结果是(应用log4j之前的信息):

?

Created a new author, [Id = 1. Name = Daniel. ]Created a new author, [Id = 2. Name = David. ]Created a new column, {Id = 1. Name = catelog.computer. }aticle [Think in java] added to -> catelog.computeraticle [Getting started Jboss] added to -> catelog.computerCreated a new column, {Id = 2. Name = catelog.Math. }aticle [middle school of math] added to -> catelog.Mathaticle [math algorithm] added to -> catelog.Math 4 articles are added to author 2!! find column information: id = 1, name = catelog.computerit has article -> aritlce id: 1, article name: Think in java, artilce author id: 2it has article -> aritlce id: 2, article name: Getting started Jboss, artilce author id: 2 author whose id is 2 has been deleted, also whose articles... article of author whose id is 1 >> article id: 1, name: Think in javaarticle of author whose id is 1 >> article id: 2, name: Getting started Jboss
?

6、在hibernate中使用native sql

?

在Article.hbm.xml中增加如下内容:

?

<set name="authorNames" table="tb_articles_author">    <key column="article_id" />    <element column="author_id" type="string"        formula="(select tb_authors.name FROM tb_authors where tb_authors.id=author_id)" /></set>
?

<element>表达通过关联表连接的,加上formula属性来获得name字段的内容,从中我们可以看到Hibernate对native SQL的支持,这个要注意formula值要加括号(这个是什么原因还有待研究,MySql不加不行,HSQL DB不加可能可以)

?

并在Article bean类中增加如下部分:

?

// to store all authors that respond to a article.public Set<String> getAuthorNames(){    if (authorNames == null)        authorNames = new HashSet<String>();    return this.authorNames;}public void setAuthorNames(Set<String> authorNames){    this.authorNames = authorNames;}
?

7、简单的缓存
?
使用缓存是提高效率的一种有效手段,Hibernate在session中就有一个缓存,就是所讲的是JVM级别的二级缓存,默认情况下使用EHCache来实现,也可以通过配置文件中的hibernate.cache.provider_class来指定缓存策略。
?
修改hibernate.cfg.xml加入
?
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
?
通过在类或集合的映射Author.hbm.xml中加入<cache>来使用缓存,必须加在<class>下面第一行!!其有几个选择read-only,read-write,transactional,等然后在执行查询时 注意了 ,如果是条件查询,或者返回所有结果的查询,此时session.find()方法 不会获取缓存中的数据。只有调用query.iterate()方法时才会调缓存的数据。
?
<cache usage="read-write"/>
?
总结

?

通过以上实例对hibernater的一些基本应用有了初步了解,最后有一个概念要说明一下,Session,应用层与持久层进行交互操作的一个生命周期很短的线程对象,其中隐藏了JDBC连接,也是Transcation的工厂,持有一个会话级缓存;SessionFactory,顾名思义就是session工厂,它是编译后的针对单一数据库映射的缓存,SessionFactory是线程安全的,可以在进程或集群层次上提供事务间可重用的数据缓存;Persistent Objects,即持久化对象,是带有持久化状态的且具有业务功能的单线程对象,可以是普通的JavaBean/POJO,唯一不同是它们与一个Session相关联,当Session关闭后这些对象将脱离持久化状态可被应用程序任意使用。更多可以去找Hibernate体系结构图看看。

?

热点排行