5.Hibernate

说起hibernate,肯定很多人一肚子苦水,也肯定很多人满口称赞,说大幅提高开发效率。

Hibernate是个让人爱又让人恨的东西。当时Hibernate的创造者的想法非常好,就是利用这个框架来屏蔽数据库的差异,做到无论是mysql、oracle、sqlserver还是其他,对开发都不影响,开发者只关注业务处理。

三种状态,临时、持久、游离

学Hibernate第一个要了解的概念就是Hibernate对象的三种状态。确实非常难以理解,我学了好多年,也是近些年才慢慢理解的。我是06年就开始学习Hibernate的,当时是2.0版本,教材是上海交大孙卫琴的精通Hibernate。记忆尤深,主要是这本书看了好多好多遍,讲的太高深苦涩了。
我说一下我对这个状态的理解:

  • 临时:Person person=new Person(),这个person就是临时状态,跟数据库无关的,如果线程结束,对象被垃圾回收,这个对象也就不存在了。
  • 持久:这个好理解,就是数据库里也有对应的记录,比如Person person=session.load(1);
  • 游离:这个比较难理解,举个例子,比如新增person,执行完session.save(person);然后还没有提交数据库,这个状态就是游离状态,还没有完全持久化,不过person这个对象已经有对应的id主键了。如果继续执行session.commit();,那这个对象就变为持久化了。

确实好难理解,说着说着我就晕了。不过没关系,真到用起来,碰到问题自然而然就理解了。

对象关联关系

对象的关联关系有1对1,1对多,多对1,多对多,还分有中间表关联,没有中间表关联等等多种情况。基本一本Hibernate的教程至少三分之一是讲这些内容。确实很高深,以纯面向对象的理念来开发数据库编程。
不过多数开发人员搞不清这些关联关系,完全对照着数据库表结构建对象。Hibernate设计之初,是先设计领域模型,然后根据领域模型的关系进行反向工程,推出数据库设计。咱们一般是不相信Hibernate的领域模型的,或者不相信自己的设计能力,更相信数据库的设计能力,都是先建表,然后倒推领域模型,最终出的结果就是四不像了。而且myeclipse工具帮了倒忙,算是Hibernate的神助攻,推出数据库的反向工具。
还有一个问题,多数项目都会遇到这个问题,为了简化开发,各个对象的关联关系都取消了,只是简单利用Hibernate 的增删改的简化方法,核心的查询反而没用到。我曾经问很多人,项目用到Hibernate了,好处在哪?仅仅一句话,不用写增删改sql了。这其实会暴露更多的问题,比如update非全字段,仅仅几个字段怎么处理?Hibernate的好处一点没用到,反而额外增加了开发难度。

Hibernate调优

这基本是所有开发人员后期面对的一个问题,Hibernate性能有问题,遇到数据量大的表,查询有问题,或复杂查询写不了,还得依赖原生sql来完成,比如group by、left join等等。所以本该数据库要做的事情,拿到程序里来写了,而且写完让人看不懂,确实难懂,因为Hibernate会根据对象映射关系生成自己的sql,全是别名,很难理解。

Hibernate的学习曲线

Hibernate的学习非常高,可以毫不夸张的讲,没几个月的时间很难深入理解。但是还有很多项目用这个,原因就是如果业务逻辑不复杂的话,可以快速开发,增删改查基本都不用写代码。我以前做过一个项目,dao层用的泛型dao,service层用的泛型service,Controller层用的泛型Controller,全基于接口编程,只要建好各个类名,一句话都不用写,整个功能就完成了,包括增删改、分页、取单条记录等等,超级牛逼啊。这不就实现了无招胜有招吗,一句代码不写,功能全部完成,而且还不可能出错。反过来讲,如果要改一个逻辑,肯定蒙圈,没代码改什么啊!

说了很多,下面还是得写个例子来讲解一下什么是Hibernate的。

pom.xml添加依赖

<dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.18</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>3.6.10.Final</version>
        </dependency>
        <dependency>
            <groupId>javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.12.1.GA</version>
        </dependency>

这里版本用的比较老,我也没办法,因为Hibernate变化太快,现在都是5点几版本了,我是好几年没用,跟不上时代了,不过没关系,原理都没变。
这里强调一下,Hibernate3.6以后持久化是基于Hibernate-jpa-2.0,这个东西和WebLogic自带的有冲突,强烈建议如果选用Hibernate,一定要先在weblogic部署,看有没有问题。我有几次就是掉进坑了

hibernate.cfg.xml 连接数据库的配置

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost/test</property>
        <property name="connection.username">root</property>
        <property name="connection.password">root</property>
        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">2</property>
        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <!-- Enable Hibernate's automatic session context management <property name="current_session_context_class">thread</property> -->
        <!-- Disable the second-level cache -->
        <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">true</property>
        <!-- Drop and re-create the database schema on startup -->
        <property name="hbm2ddl.auto">update</property>
        <!-- <mapping resource="com/critc/model/Staff.hbm.xml" /> -->
        <mapping class="com.critc.model.Staff" />
    </session-factory>
</hibernate-configuration>

这里面的属性都比较好理解,稍微看下书就能明白意思。

model

@Entity
@Table(name = "staff")
public class Staff {
    private int id;
    private String name;//
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

这里是采用注解来实现的,现在都采用注解了,配置的时代早过去了。
记住几点,必须有@ID,字段的注解尽量写在get方法上,当时讲过原因,不过写在字段上更好理解一些,也起作用。

具体操作类

public class HibernateTest {
    public static void main(String[] args) {

        Configuration cfg = new Configuration();
        SessionFactory sessionFactory = cfg.configure().buildSessionFactory();
        Session session = sessionFactory.openSession();
        session.beginTransaction();

        //新增
        Staff staff = new Staff();
        staff.setName("Hibernate");
        session.save(staff);
        //获取单个
        Staff staff2 = (Staff) session.get(Staff.class, staff.getId());
        if (staff2 != null)
            System.out.println(staff2.getName());
        //修改
        staff2.setName("改后名字Hibernate2");
        session.save(staff2);

        //查询 HQL
        Query q = session.createQuery("from Staff");
        List<Staff> list = q.list();
        for (Staff staff3 : list) {
            System.out.println(staff3.getName());
        }

        //删除
//      session.delete(staff2);
        session.getTransaction().commit();
        session.close();
        sessionFactory.close();
    }
}

上面是举个例子,简单的增删改查。

写这篇文章的目的不是教给大家Hibernate怎么用,而是说Hibernate学起来会很难,如果你有信心,有毅力,完全可以一战!

源码下载

本工程详细源码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容