Hibernate系列(二)Hibernate详解

一.Hibernate测试代码

直接上代码,具体解释见代码注释

Hibernate主配置文件hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 必须导入约束文件hibernate-configuration-3.0.dtd -->
<!-- 约束文件路径
...\hibernate-release-5.0.7.Final\project\hibernate-core\src\main\resources\org\hibernate\hibernate-configuration-3.0.dtd
 -->
  <!-- 导包后,可以从下面路径的文件中复制约束声明
        hibernate-core-5.0.7.Final.jar/org/hibernate/hibernate-configuration-3.0.dtd -->
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    <!-- hibernate的主配置文件,必须放在src目录下,命名为hibernate.cfg.xml -->
    <hibernate-configuration>
<session-factory>
    <!-- 关于配置的文件描述,hibernate提供了hibernate.properties文件
        路径:...\hibernate-release-5.0.7.Final\project\etc
    -->
    <!-- #hibernate.dialect org.hibernate.dialect.MySQLDialect
        #hibernate.dialect org.hibernate.dialect.MySQLInnoDBDialect
        #hibernate.dialect org.hibernate.dialect.MySQLMyISAMDialect
        #hibernate.connection.driver_class com.mysql.jdbc.Driver
        #hibernate.connection.url jdbc:mysql:///test
        #hibernate.connection.username gavin
        #hibernate.connection.password -->
    <!-- 数据库驱动 -->
    <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
    <!-- 数据库url -->
    <property name="hibernate.connection.url">jdbc:mysql:///my?useUnicode=true&amp;characterEncoding=utf-8</property>
    <!-- url后设置的是读取使用的编码,必须于数据库一致。其中 amp;  不能省略,原因未知-->
    <!-- 数据库连接用户名 -->
    <property name="hibernate.connection.username">root</property>
    <!-- 数据库连接密码 -->
    <property name="hibernate.connection.password">password</property>
    <!-- 数据库方言 不同的数据库中,sql语法略有区别. 
        指定方言可以让hibernate框架在生成sql语句时.针对数据库的方言生成. 
        sql99标准: DDL 定义语言 库表的增删改查 DCL 控制语言 事务 权限 DML 操纵语言 增删改查 
        注意: MYSQL在选择方言时,请选择最短的方言. -->
    <property name="hibernate.dialect">
        org.hibernate.dialect.MySQLDialect
    </property>
    <!-- #hibernate.show_sql true
        #hibernate.format_sql true-->
    <!-- 将hibernate生成的sql语句打印到控制台 -->
    <property name="hibernate.show_sql">true</property>
    <!-- 将hibernate生成的sql语句格式化(语法缩进) -->
    <property name="hibernate.format_sql">true</property>
    <!-- ## auto schema export

        #hibernate.hbm2ddl.auto create-drop
        #hibernate.hbm2ddl.auto create
        #hibernate.hbm2ddl.auto update
        #hibernate.hbm2ddl.auto validate-->
    <!-- ## auto schema export 自动导出表结构. 自动建表 
        #hibernate.hbm2ddl.auto create 自动建表.每次框架运行都会创建新的表.以前表将会被覆盖,表数据会丢失.(开发环境中测试使用) 
        #hibernate.hbm2ddl.auto create-drop 自动建表.每次框架运行结束都会将所有表删除.(开发环境中测试使用) 
        #hibernate.hbm2ddl.auto update(推荐使用) 自动生成表.如果已经存在不会再生成.如果表有变动.自动更新表(不会删除任何数据). 
        #hibernate.hbm2ddl.auto validate 校验.不自动生成表.每次启动会校验数据库中表是否正确.校验失败. -->
    <property name="hibernate.hbm2ddl.auto">update</property>
    <!-- 指定hibernate操作数据库时的隔离级别## specify a JDBC isolation level
        #hibernate.connection.isolation 1|2|4|8
        二进制
        0001            1           读未提交
        0010            2           读已提交
        0100            4           可重复读        mysql默认
        1000            8           串行(xing)化
    -->
    <property name="hibernate.connection.isolation">4</property>
    <!-- 指定session与当前线程绑定.hibernate.properties文件中没有描述,要背下来名称-->
    <!-- 加入此项后getCurrentSession方法才能使用,否则会报错 -->
    <property name="hibernate.current_session_context_class">thread</property>
    <!-- 引入orm元数据 路径书写: 填写src下配置的xml文件的路径 -->
    <property name="dialect"></property>
    <mapping resource="cjx/user/Hibernate.xml" />
</session-factory>
</hibernate-configuration>

POJO类User.java

public class User {//实体类
    /*实体(bean)类创建规则
     * 1.持久化类提供无参数构造
     * 2.成员变量私有,提供公有get/set方法访问
     * 3.持久化类中的属性,应尽量使用包装类型.(jdk有自动装箱和拆箱功能,基本类型没有null值)
     * 4.持久化类需要提供oid(与主键对应的属性).与数据库中的主键列对应.(如果一个表没有主键,hibernate不能使用)
     * 5.不要用final修饰class().(hibernate使用cglib代理生成代理对象.代理对象是继承被代理对象.如果被final修饰.将无法生成代理.)
     */

    private String id;
    private String username;
    private String password;
    private String test;
    public String getTest() {
        return test;
    }
    public void setTest(String test) {
        this.test = test;
    }
    public String getUsername() {
        return username;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
    }
}

Hibernate映射文件Hibernate.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- 必须导入约束文件hibernate-mapping-3.0.dtd -->
<!-- 约束文件路径
...\hibernate-release-5.0.7.Final\project\hibernate-core\src\main\resources\org\hibernate\hibernate-mapping-3.0.dtd
 -->
 <!-- 导包后,可以从下面路径的文件中复制约束声明
        hibernate-core-5.0.7.Final.jar/org/hibernate/hibernate-mapping-3.0.dtd -->
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!-- hibernate的orm元数据配置文件-->
<!-- 配置表与实体对象的关系 -->
<!-- package属性(可选):填写一个包名.
好处:在元素内部凡是需要书写完整类名的属性,可以直接写简单类名. -->
<hibernate-mapping package="cjx.user">
<!-- class元素: 配置实体bean与表的对应关系. name: 完整类名 table:数据库表名 -->
<class table="user" name="cjx.user.User">
<!-- id元素:配置主键映射的属性 name: 填写主键对应bean的属性名 
column(可选): 填写表中的主键列名.默认值:列名会默认使用属性名 
type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型. 
每个类型有三种填法: java类型|hibernate类型|数据库类型 
not-null(可选):配置该属性(列)是否不能为空. 默认值:false 
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度 -->
<id name="id">
<!-- generator:主键生成策略 -->
<!-- 每条记录录入时,主键的生成规则,适用于代理主键 -->
<!-- 
     * 主键生成策略:
     * 1.自然主键
     * assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.
     * 2.代理主键
     * identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键(指定了主键也无效).
     *              sequence: Oracle中的主键生成策略.
     *              increment(了解)(线程不安全): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值主键类型必须为整型.            
     *              hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
     *              native:hilo+sequence+identity 自动三选一策略.
     *              uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
 -->
<generator class="assigned"></generator>
</id>
<!-- property元素:除id之外的普通属性映射
 name: 填写属性名 
 column(可选): 填写列名 
 type(可选):填写列(属性)的类型.hibernate会自动检测实体的属性类型. 
每个类型有三种填法: java类型|hibernate类型|数据库类型 
not-null(可选):配置该属性(列)是否不能为空. 默认值:false 
length(可选):配置数据库中列的长度. 默认值:使用数据库类型的最大长度 -->
<property name="username" column="username"/>
<property name="password" column="password"/>
<!--  用于演示hibernate的自动建表功能:hibernate.hbm2ddl.auto
<property name="test" column="test"/>
-->
</class>
</hibernate-mapping>

测试代码Hibernate.java

public class Hibernate {
    @Test
    //hibernate操作代码演示
    public void funone(){
        //1.创建,调用空参构造
         /* Configuration conf = new Configuration();
         * 读取指定主配置文件 => 空参加载方法,加载src下的hibernate.cfg.xml文件
         * conf.configure();
         * 读取指定orm元数据(扩展),如果主配置中已经引入映射配置.不需要手动加载
         * conf.addResource(resourceName);
         * conf.addClass(persistentClass);
         */
        // Configuration对象功能: 配置加载类.用于加载主配置,orm元数据加载
        Configuration config = new Configuration().configure();
        //2.根据配置信息,创建 SessionFactory对象
        /* SessionFactory对象功能: 用于创建操作数据库核心对象session对象的工厂.创建session对象
            注意:1.SessionFactory 负责保存和使用所有配置信息.消耗内存资源非常大.
                2.SessionFactory属于线程安全的对象设计.
            结论: 保证在web项目中,只创建一个sessionFactory.
        */
        SessionFactory sessionFactory = config.buildSessionFactory();
        //3.获得session.打开一个新的session对象
        /*session对象功能: 表达hibernate框架与数据库之间的连接(会话).
            session类似于JDBC的connection对象. 还可以完成对数据库中数据的增删改查操作.
            session是hibernate操作数据库的核心对象
         * 扩展
            获得一个与线程绑定的session对象
            sessionFactory .getCurrentSession();
         */
        Session session = sessionFactory.openSession();
        //4. session获得操作事务的Transaction对象
        /*获得操作事务的transaction 对象
         * Transaction transaction  = session.getTransaction();
         * 开启事务并获得操作事务的transaction 对象(建议使用)
         *Transaction tx2 = session.beginTransaction();
         */
        Transaction transaction = session.beginTransaction();
//      //----------------------------------------------
//      //session的增加//web开发时可以使用beanutil.populate()将参数封装到对象
        User uz = new User();//瞬时状态
        uz.setId("123456");//瞬时状态
        uz.setUsername("check is ok");//瞬时状态
        uz.setPassword("123456");//瞬时状态
        session.save(uz);//将瞬时状态转换为持久化状态
//      //----------------------------------------------
//      //----------------------------------------------
//      //session的修改
//         //1.获得要修改的对象
//        // 2.修改
//        //3 执行update
//      User  ux= session.get(User .class, "1");//此时得到的是持久化状态
//      ux.setUsername("i  have change it");
//      ux.setPassword("11111111");
//          session.update(ux);//因为是持久化状态,所以不写此句也可以修改
            //持久化状态对象的任何变化都会在事务提交时自动同步到数据库中
            /*三个对象状态:瞬时状态,持久化状态,游离(托管)状态
             * 瞬时状态:没有id,不在session缓存中
             * 持久化状态:有id,在session缓存中
             * 游离(托管)状态:有id,不在session缓存中
             * 注:有id指的是有与数据库对应的id值
             * 三个对象状态可以通过这些方法进行转换
             * 瞬时状态:new(得到瞬时状态),save(转换为持久化状态)
             * 持久化状态:get(得到持久化状态),delete(转换为瞬时状态),close(转换为游离状态)
             * 游离(托管)状态:update(转换为持久化状态)
             * 拓展:session.saveOrUpdate(object);方法可以直接将对象转换为持久化状态
             */
//      //----------------------------------------------
//      //----------------------------------------------
//      //session的删除
//      //1.获得要修改的对象
//      //2.调用delete删除对象
//          User ud = session.get(User.class, "545654654564as");
//          session.delete(ud);
//      //----------------------------------------------
//      //----------------------------------------------
//      //session的查询
//       User  uc= session.get(User .class, "1");
//       User  uc1= session.get(User .class, "1");
//       User  uc2= session.get(User .class, "1");
         /*1.关于缓存,此处证明缓存存在,用于查询
          * SQL语句只会执行一次,得到的对象相同
          * 查询时:第一次查询会将对象放入session缓存,再次查询时,会先查找session缓存
          *2.关于快照,快照是指修改数据库数据时的缓存,用于修改
          *提交事务时会将快照与数据库对比,如果数据不同就会修改数据库数据
          *修改时:使用快照对比实体类对象和数据库数据的属性区别,只执行一次修改
          *正因为有缓存(快照)存在,所以才有持久化状态
          */
//       System.out.println(uc);
//       System.out.println(uc==uc1);
//       System.out.println(uc1==uc2);
        /*load方法和get方法
         * get方法:调用方法时直接返回查询结果
         * load方法:使用对象时才返回查询结果
         *  load方法又叫延迟加载,可以配置lazy属性进行控制
         *  lazy:true加载时不查询,使用时才查询
         *  lazy:false加载时立即查询
         */
//      //----------------------------------------------
        transaction.commit();//提交事务时会自动关闭资源
//      transaction.rollback();//回滚事务
        session.close();//释放资源
        sessionFactory.close();//释放资源
    }

    @Test
    //测试主键生成策略,保存用户
    public void funtwo(){
        /*关于主键
         * 主键:不能为空,不能重复
         * 
         * 主键类型:
         * 1.自然主键:数据库表中有可以代表主键的列,如身份证号
         * 2.代理主键:数据库表中没有可以代表主键的列,创建一个没有意义的列作为主键
         * 
         * 主键生成策略:
         * 1.自然主键
         * assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.
         * 2.代理主键
         * identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键.
         *              sequence: Oracle中的主键生成策略.
         *              increment(了解)(线程不安全): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值.         
         *              hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
         *              native:hilo+sequence+identity 自动三选一策略.
         *              uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
         */
        //1.获得session
        Session session = HibernateUtil.openSession();
        //2.控制事务
        Transaction tx = session.beginTransaction();
        //3.执行操作
        User uz = new User();
        uz.setUsername("test and test");
//      uz.setPassword("123456");
        session.save(uz);
        //4.提交事务,关闭资源
        tx.commit();
        session.close();
    }
    @Test
    //测试事务操作
    public void funthree(){
        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();
        try {
            User uz = new User();
            uz.setId("123456");
            uz.setUsername("test and test");
            session.save(uz);
            int i=1/0;//被除数不能为0
            System.out.println(i);
        } catch (Exception e) {
            tx.rollback();//回滚事务
            System.out.println("?????????");
        }
        tx.commit();
        session.close();
    }

}

工具类HibernateUtil.java

public class HibernateUtil {
//  用于测试的主函数
//  public static void main(String[] args) {
//      System.out.println(HibernateUtil.openSession());
//  }
    private static SessionFactory sf;
    static{
        //1.创建,调用空参构造
        Configuration conf = new Configuration().configure();
        //2.根据配置信息,创建 SessionFactory对象
         sf = conf.buildSessionFactory();
    }
    //获得session => 获得全新session
    public static Session openSession(){
                Session session = sf.openSession();
                return session;
    }
    //获得session => 获得与线程绑定的session
    public static Session getCurrentSession(){
        Session session = sf.getCurrentSession();
        return session;
    }   
}

查询测试代码HibernateCheck.java

public class HibernateCheck {
    @Test
    //HQL查询-hibernate Query Language(多表查询,但不复杂时使用)
    public void funone(){
        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();
        //1.写HQL语句
        //HQL语句不能出现数据库信息,要使用实体类的信息
//      String hql="from  cjx.user.User";//完整写法
        String hql="from  User order by id";//简单写法,基本查询,查询所有user对象
//      String hql="from  User  where id = 1";//条件查询
//      String hql="from  User  where id = ?";//问号占位符查询
//      String hql="from  User  where id = :name ";//命名占位符查询,冒号+自定义的名字
        //2.创建查询对象
        Query query = session.createQuery(hql);
//      query.setParameter(0, "1");//问号占位符查询设置参数,位置+参数
//      query.setParameter("name", "1");//命名占位符查询设置参数,名字+参数
        /*分页查询 */
        //设置分页信息
//      query.setFirstResult(0);//开始的索引
//      query.setMaxResults(1);//要获取几条索引
        //3.获得查询结果
        List<User> list = query.list();//返回list结果
//      Object uniqueResult = query.uniqueResult();//返回唯一结果
        System.out.println(list);
        /*统计查询
         * count  计数
         * sum 求和 select sum(id) from User
         * avg  求平均数
         * max  求最大
         * min 求最小
         */
    }
    @Test
    //Criteria查询(单表条件查询),无语句面向对象查询
    public void funtwo(){
        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();
        Criteria criteria = session.createCriteria(User.class);//基本查询,查询所有user对象
        /*扩展 */
//      criteria.add(Restrictions.eq("id", "1"));//条件查询,直接调用Restrictions方法
        /*关于Restrictions方法
         * >:gt
         * >=:ge
         * <:lt
         * <=:le
         * ==:eq
         * !=:ne
         * in:in
         * is null:isNull等等
         */
        /*扩展 */
        /*分页查询 */
        //设置分页信息
//      criteria.setFirstResult(1);//开始的索引
//      criteria.setMaxResults(1);//要获取几条索引
        /*分页查询 */
        List<User> list = criteria.list();
        System.out.println(list);
        /*使用函数*/
//      criteria.setProjection(Projections.rowCount());//设置查询的聚合函数=》总行数
//      long x=(long) criteria.uniqueResult();//此处用int会报错
//      System.out.println(x);
        /*使用函数 */
        tx.commit();
        session.close();
        /*离线的criteria
         * criteria可以脱离session创建,组装查询条件,直接在web层查询
        DetachedCriteria dc=DetachedCriteria.forClass(User.class);//创建离线criteria
        dc.add(Restrictions.eq("id", "1"));//组装查询条件
        Criteria c=dc.getExecutableCriteria(session);//关联session
        List<User> clist = c.list();
        System.out.println(clist);
         */
    }
    @Test
    //原生SQL查询(复杂的业务查询)
    public void funthree(){
        Session session = HibernateUtil.openSession();
        Transaction tx = session.beginTransaction();
        /*基本查询*/
        String sql="select * from user";
        SQLQuery query = session.createSQLQuery(sql);
        /*条件查询*/
//      String sql="select * from user where id=?";
//      SQLQuery query = session.createSQLQuery(sql);
//      query.setParameter(0, "1");
        /*条件查询*/
        /*分页查询*/
//      String sql="select * from user limit ?,?";
//      SQLQuery query = session.createSQLQuery(sql);
//      query.setParameter(0, 0);
//      query.setParameter(1, 1);
        /*分页查询*/
        /*不指定类型时*/
//      List<Object[]> list = query.list();//注意泛型要用<Object[]>
//      for (Object[] obj : list) {
//          System.out.println(Arrays.toString(obj));
//      }
        /*不指定类型时*/
        System.out.println("————————————————");
        /*指定类型时*/
        query.addEntity(User.class);//指定将结果集封装到哪个对象中
        List<User> list2 = query.list();
        System.out.println(list2);
        /*指定类型时*/
        tx.commit();
        session.close();
    }   
}

猜你喜欢

转载自blog.csdn.net/bestmy/article/details/81057129