Hibernate 特性 操作各种语法 火推05

Hibernate

是一款开源的ORM框架,hibernate是在我们的MVC设计模式中,充当的是持久化层,负责数据的操作交互。

Jboss

2001-2004

搭建步骤:

1:导包

    <!-- hibernate -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.2.21.Final</version>
    </dependency>

2:加载hibernate配置文件

    hibernate.cfg.xml
    note.hbm.xml

hibernate.cfg.xml:

<?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">

<hibernate-configuration>
    <session-factory>
        <!-- 方言 -->
        <property name="dialect">
            org.hibernate.dialect.MySQLDialect
        </property>

        <!-- 数据库连接信息 -->
        <property name="connection.url">
            jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf8
        </property>
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- 显示底层sql语句 -->
        <property name="show_sql">true</property>
        <property name="format_sql">true</property>

        <mapping resource="hbm/Note.hbm.xml" />

    </session-factory>
</hibernate-configuration>

note.hbm.xml:

<?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>

    <!-- name:代表数据库表所对应的java实体对象信息
         table:代表的是数据库表名称
     -->
     <class name="com.xdl.entity.Note" table="note">

        <!-- 必须要指定主键ID -->
        <id name="id" type="integer" column="id"></id>

        <!-- 其它字段使用property属性标签定义,其中:
            name:代表数据库表中的字段所对应的实体对象中的属性名称
            type:代表数据库表中的字段类型,注意:首字母必须小写
            column:代表数据库表中的字段名称
         -->
        <property name="context" type="string" column="context"></property>
        <property name="publishTime" type="date" column="publishTime"></property>
        <property name="likeCount"  type="integer" column="likeCount"></property>
        <property name="userId"  type="integer" column="userId"></property>
     </class>

</hibernate-mapping>

演变:

jdbc--->jdbTemplate--->mybatis---->hibernate

hibernate与mybatis的区别?

1:hibernate学习难度大于mybatis
2:hibernate的扩展性和移植性要比mybatis强
3:hibernate支持count、sum、avg函数,但是不支持一些类型转换,比如:日期转换,字符转换等
4:hibernate支持事务,并且自支持缓存,如:一级缓存、二级缓存和查询缓存,可以使用第三方缓存技术
5:hibernate不建议使用left join,而mybatis可以支持
6:hibernate自支持分页条件,而mybatis需要配置分页插件
7:hibernate一般应用与老系统的维护和开发,目前流行的企业解决方案为mybatis
8:hibernate不需要写sql语句,是自动生成的,而mybatis需要写sql语句

数据库工具类

/**
 * 数据库工具类,获取数据库连接session
 * @author likang
 * @date   2018-1-11 上午9:58:18
 */
public class HibernateUtils {

    public static Session getSession(){
        Configuration conf = new Configuration();
        conf.configure("hibernate.cfg.xml");
        SessionFactory sessionFactory = conf.buildSessionFactory();
        Session session = sessionFactory.openSession();
        return session;
    }
}

增删改查操作

问题:(session.close())

1:数据库游标越界
2:too many connect

解决方式:

1:重启数据库----命令重启---service mysqld stop/start/restart
2:使用命令查询当前连接数据库的进程号,直接kill
3:经常在开发环境使用--借助连接数据库的客户端

TestHibernate.java:

/**
 * 测试hibernate框架操作
 * @author likang
 * @date   2018-1-11 上午10:24:19
 */
public class TestHibernate {


    /**
     * 查询操作
     */
    @Test
    public void test1(){
        Session session = HibernateUtils.getSession();
//Note.hbm.xml中指定的表,查询数据库中note表id为16条的信息,自动生成sql语句,不需要手写sql语句
        Note note = (Note) session.get(Note.class, 16);
        if (note != null) {
            System.out.println(note.getContext());
        }else{
            System.out.println("查询数据为空");
        }
    }

    /**
     * 增加操作
     *  写操作:需要开启事务,执行完毕之后,需要关闭
     */
    @Test
    public void test2(){
        Session session = HibernateUtils.getSession();
        Note note = new Note();
        note.setId(201);
        note.setContext("java13测试数据2");
        note.setLikeCount(100);
        note.setUserId(1);
        note.setPublishTime(new Date(System.currentTimeMillis()));
        Transaction ts = session.beginTransaction();//开启事务
        session.save(note);
        ts.commit();//提交----flush---commit
        session.close();
    }

    /**
     * 删除操作
     *      后台实际执行了两步sql
     *      1:先执行查询操作,如果数据存在,则继续执行delete语句,如果不存在,则不执行删除语句
     */
    @Test
    public void test3(){
        Session session = HibernateUtils.getSession();
        Note note = new Note();
        note.setId(200);
        Transaction ts = session.beginTransaction();//开启事务
        session.delete(note);
        ts.commit();//提交----flush---commit
        session.close();
    }


    /**
     * 修改操作
     *      在修改数据之前,一般是先进行查询,将数据结果集,赋值给note
     * 
     */
    @Test
    public void test4(){

        Session session = HibernateUtils.getSession();

        Note note = (Note) session.get(Note.class, 201);
//      Note note = new Note();
//      note.setId(201);
        note.setLikeCount(300);

        Transaction ts = session.beginTransaction();//开启事务
        session.update(note);
        ts.commit();//提交----flush---commit
        session.close();

    }
}

Hibernate主键管理

1.sequence 序列

一般适用于oracle数据库

2.identity 主键自增

一般用于mysql、SqlServer数据库

3.native 自动匹配

可以自动匹配当前数据库类型,
如果当前数据库是mysql,则自动将主键设置为identity,
如果当前数据库为oracle,则自动将主键识别为sequence

4.increment 自动获取主键+1

自动的去数据库获取最大值的ID,然后+1,设置为主键ID

5.uuid/hilo 随机算法和高低位算法

32---varchar(32)

6.assigned

需要我们自动的去设置主键ID,需要添加setId();

配置主键的位置:

note.hbm.xml中:

    <id name="id" type="integer" column="id">
        <!-- 指定表的主键策略 -->
        <generator class="identity"></generator>
    </id>

Hibernate查询操作

HQL查询

HQL:hibernate query Language(面向对象的查询)----对象化  (实体)

select * from Note(实体类名)

SQL:Structured Query Language(面向结构的查询)---结构化 (数据库表和表字段)

select * from note(数据库表名)

HQL与SQL有什么区别?

1:HQL是面向对象的查询,SQL是面向结构的查询
2:HQL对查询语句的大小写非常敏感,而SQL对查询语句的大小写字段属性依赖于我们的数据库配置信息
3:HQL在进行查询的时候,使用的是类名和属性名称,而SQL在查询的时候,使用的是数据库表名和字段名
4:如果我们是需要查询表中所有的数据,那么HQL,可以省略select *,直接使用 from Note,SQL则不能省略
5:HQL不支持类型转换,如:日期转换、字符转换等,SQL支持
6:HQL不能进行特别复杂的查询操作,也就是说,不建议使用left join,而SQL,可以无限制的使用left join等关联,进行复杂查询

示例:

public class TestHQL {

    /**
     * 查询操作
     */
    @Test
    public void test1(){
        Session session = HibernateUtils.getSession();
        String hql = "from Note";//‘Note’代表类名,如果查询全部,则可以省略select *
        Query query = session.createQuery(hql); //返回的是Query对象
        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("笔记内容为:"+list.get(i).getContext()+"--------时间为:"+list.get(i).getPublishTime());
            }
        }
    }

    /**
     * 带有where条件的查询
     */
    @Test
    public void test2(){
        Session session = HibernateUtils.getSession();
        String hql = "from Note where publishTime >?";
        Query query = session.createQuery(hql);
        query.setDate(0, Date.valueOf("2017-12-01"));//第一个参数代表hql中参数的下标,从0开始,第二个参数为赋值

        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("id:"+list.get(i).getId()+"笔记内容为:"+list.get(i).getContext()+"--------时间为:"+list.get(i).getPublishTime());
            }
        }
    }

    /**
     * 分页查询
     */
    @Test
    public void test3(){

        Session session = HibernateUtils.getSession();
        String hql = "from Note";//‘Note’代表类名,如果查询全部,则可以省略select *
        Query query = session.createQuery(hql);
        query.setFirstResult(6);//代表的是从数据库第几条数据开始,不包含当前条数
        query.setMaxResults(2);//一共获取多少条

        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("id:"+list.get(i).getId()+"笔记内容为:"+list.get(i).getContext()+"--------时间为:"+list.get(i).getPublishTime());
            }
        }
    }

    /**
     * 查询个数
     */
    @Test
    public void test4(){
        Session session = HibernateUtils.getSession();
        String hql = "select count(*) from Note";
        Query query = session.createQuery(hql);

        Long count = (Long) query.uniqueResult();
        System.out.println("一共有:"+count);

    }
}
Criteria查询

复杂条件查询:

示例:

public class TestCriteria {


    /**
     * 查询操作
     */
    @Test
    public void test1(){

        Session session = HibernateUtils.getSession();
        Criteria criteria = session.createCriteria(Note.class);//直接实体对象映射就可以查询note表
        List<Note> list = criteria.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("内容为:"+list.get(i).getContext());
            }
        }
    }

    /**
     * 1:select * from note where note.publishTime > '2017-12-01'
     */
    @Test
    public void test2(){

        Session session = HibernateUtils.getSession();
        Criteria criteria = session.createCriteria(Note.class);
        //select * from note where note.publishTime > '2017-12-01'
//      criteria.add(Restrictions.gt("publishTime", Date.valueOf("2017-12-01")));//publishTime > '2017-12-01'

        //select * from note where note.publishTime > '2017-12-01' and userId = 1
//      criteria.add(Restrictions.eq("userId", 1));// 时间publishTime 和userId拼接成一个sql语句了

        select * from note where note.publishTime > '2017-12-01' or userId = 1
        criteria.add(Restrictions.or(Restrictions.gt("publishTime", Date.valueOf("2017-12-01")),
                Restrictions.eq("userId", 1)));

        criteria.addOrder(Order.desc("publishTime"));//倒序
                                                     //Order.asc("publishTime");正序
        List<Note> list = criteria.list();

        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println("时间为:"+list.get(i).getPublishTime()+"--------"+"内容为:"+list.get(i).getContext());
            }
        }

    }
}
NativeSQL查询

原生sql查询:

/**
 * 原生sql查询
 * @author likang
 * @date   2018-1-11 下午2:41:15
 */
public class TestNativeSQL {

    @Test
    public void test1(){
        Session session = HibernateUtils.getSession();
        String sql = "select * from note";//note 是数据库表名
        SQLQuery query = session.createSQLQuery(sql);
        /*List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println(list.get(i).getContext());
            }
        }*/ //会提示类型转换异常,

        List<Object[]> list = query.list();
        if (list != null && list.size() > 0) {
            for (Object[] obj : list) {
                System.out.println(obj[1]);
            }
        }
    }


    /**
     * 推荐使用的查询方式
     */
    @Test
    public void test2(){
        Session session = HibernateUtils.getSession();
        String sql = "select * from note";//note 是数据库表名
        SQLQuery query = session.createSQLQuery(sql);
        query.addEntity(Note.class);//加载数据库表映射文件信息
        List<Note> list = query.list();
        if (list != null && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                System.out.println(list.get(i).getContext());
            }
        }

    }
}

Hibernate注解应用

类名:

@Entity//指定当前实体为一个映射关系
@Table(name="note")//映射到数据库note表

属性字段名:

主键:
@Id//指定实体对象主键
@Column(name="id")//指定对应到数据库表中的字段名称
@GeneratedValue(strategy=GenerationType.IDENTITY)//设置主键的生成策略

其它字段:
@Column(name="context")

需要将hibernate.cfg.xml中的加载映射文件修改为:

<mapping class="com.xdl.entity.Note"/>

Hibernate特性

延迟加载

hibernate中有一些特定的api具有延迟加载的特性,在使用了具有延迟加载特性的api之后,不会立刻去开启事务并指定hql语句,直到使用对象的时候,才会去调用事务,执行查询。

load:具有延迟加载特性
find:具有延迟加载的特性
iterate:具有延迟加载的特性

get:没有延迟加载特性
list:没延迟加载的特性

问题:(使用了延迟加载的特性API)

org.hibernate.LazyInitializationException: could not initialize proxy ...no session

解决:

明天讲(opensessionviewFilter)

示例:

@Test
public void test1(){
    Session session = HibernateUtils.getSession();

//  Note note2 = (Note) session.get(Note.class, 16);

    Note note1 = (Note) session.load(Note.class, 16);

}
缓存(性能优化)
  • 一级缓存

    hibernate默认开启一级缓存,并且不需要做任何的配置
    
    session独享
    

示例:

@Test
public void test1(){
//Session独享 打印第一条sql语句,后面的直接得到数据
    Session session = HibernateUtils.getSession();

    Note note = (Note) session.get(Note.class, 16);
    System.out.println(note.getContext());

//  Session session1 = HibernateUtils.getSession();
//  
//  Note note1 = (Note) session1.get(Note.class, 16);
//  System.out.println(note1.getContext());

}
  • 二级缓存
  • 查询缓存
 
持久化(session)

hibernate 数据状态

26113131_HJaV.jpg

状态值:

transient:临时状态

    Note note = new Note();
    此状态的数据,可以随时被GC //GC垃圾回收机制回收

persistent:持久化状态

    session.save(note);---将临时状态数据--->持久化状态数据
    session.delete(note);--->将持久化状态数据-->临时状态数据--->删除

    持久化状态的数据,永远不会自动gc的

detached:游离状态/托管状态

    session.close();---将持久---》托管
    session.update();---将托管---》持久

    游离状态可以随时被GC

 

转载于:https://my.oschina.net/u/3680357/blog/1605688

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值