• hibernate(一)helloworld、api、事务、配置文件、映射文件


    hibernate 系列
      hibernate(一)helloworld、api、事务、配置文件、映射文件
      hibernate(二)对象的三种状态、一级缓存、多对一、inverse、cascade
      hibernate(三)多对多、加载策略、懒加载、HQL查询、整合c3p0、乐观锁悲观锁
      hibernate(四)整合log4j、一对一、二级缓存

    本篇目录:

    1、hibernate 介绍
    2、ORM 介绍
    3、Java 种常用的 ORM 技术
    4、hibernate hello world 程序
    5、Hibernate-api详解
        5.1、Configuration对象
        5.2、SessionFactory对象
        5.3、Session-增删改
        5.4、Session-HQL查询
        5.5、Session-Criteria&Sql查询
        5.6、session.load()
        5.7、Transaction详解
        5.8、Query详解
        5.9、Criteria详解(了解,开发中用得不多)
        5.10、封装Hibernate工具类
    6、Hibernate-配置文件
    7、Hibernate-实体配置详解-实体规则
    8、映射文件详解

    1、hibernate 介绍    <--返回目录

      hibernate 在 javaEE 三层架构的位置

    2、ORM 介绍    <--返回目录

      ORM:对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。

      对象 Object:java 对象,此处特指 JavaBean

      关系 Relational:二维表,数据库的表

      映射 Mapping:对象的属性 与表字段 存在对应关系

    3、Java 种常用的 ORM 技术    <--返回目录

      1)JPA(Java Persistence API):JPA 通过 JDK5 注解或 XML 描述对象-关系表的映射关系(只有接口规范)

      2)Hibernate:ORM 框架,通过对象-关系映射配置,可以完全脱离底层 sql

      3)mybatis:apache 开源项目 ibatis,支持普通 sql 查询,存储过程和高级映射的优秀持久层框架

      4)apache DBUtils、Spring JDBCTemplate

    4、hibernate hello world 程序    <--返回目录

      demo 最终结构

      新建一个 Java Project

       依赖

     链接:https://pan.baidu.com/s/12nwIyodOhVCEemaAyPVPtQ 提取码:tp9w

       依赖 Add to Build Path

      创建实体类

    package com.oy.helloworld;
    public class User {
        private Integer id;
        private String username;
        private String password;
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public String getUsername() {
            return username;
        }
        public void setUsername(String username) {
            this.username = username;
        }
        public String getPassword() {
            return password;
        }
        public void setPassword(String password) {
            this.password = password;
        }
    }

      mysql 创建表

    CREATE TABLE `user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(100) DEFAULT NULL,
      `password` varchar(100) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

      hibernate 配置文件 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>
            <!-- 连接数据库的驱动 -->
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <!-- 连接数据库的地址 -->
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=UTF-8</property>
            <!-- 连接数据库的用户名 -->
            <property name="hibernate.connection.username">root</property>
            <!-- 连接数据库的密码 -->
            <property name="hibernate.connection.password">123456</property>
    
            <!-- show_sql: 操作数据库时, 会向控制台打印 sql 语句 -->
            <property name="show_sql">true</property>
            <!-- format_sql: 打印 sql 语句前, 会先将 sql 语句格式化 -->
            <property name="format_sql">true</property>
            <!-- hbm2ddl.auto: 生成表结构的策略配置。
                update(最常用):如果当前数据库中不存在表结构,那么自动创建表结构。如果存在表结构,并且表结构与实体一致,
                    那么不做修改。如果存在表结构,并且表结构与实体不一致,那么会修改表结构,会保留原有列。
                create(很少用):无论是否存在表结构,每次启动 Hibernate 都会重新创建表结构(数据会丢失) 。
                create-drop(极少用):无论是否存在表结构,每次启动 Hibernate 都会重新创建表结构。
                    每次 Hibernate 运行结束时,删除表结构。
                validate(很少用):不会自动创建表结构,也不会自动维护表结构。Hibernate只校验表结构。
                    如果表结构不一致将会抛出异常。 -->
            <property name="hbm2ddl.auto">update</property>
    
            <!-- 数据库方言配置 org.hibernate.dialect.MySQLDialect (选择最短的) -->
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
            
            <!-- hibernate.connection.autocommit: 事务自动提交,默认false  -->
            <property name="hibernate.connection.autocommit">true</property>
    
            <!-- 引入ORM 映射文件 填写src之后的路径 -->
            <mapping resource="com/oy/helloworld/User.hbm.xml" />
        </session-factory>
    </hibernate-configuration>

      映射文件 User.hbm.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC 
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
        
     <!-- ORM元数据  表对象关系映射文件 
         package: 配置该配置文件 实体类 所在的包 -->
     <hibernate-mapping package="com.oy.helloworld">
         <!--class: 配置实体与表的关系
             name : 填写实体的完整类名
             table: 与实体对应表的名称
             dynamic-insert:动态插入,默认值是false
                            true => 如果字段值为null,不参与 insert 语句
             dynamic-update:动态更新,默认值"false"
                             true => 没改动过的属性,将不会生成到 update 语句中 -->
         <class name="User" table="user">
             <!--id: 配置实体与表中 id对应
                 name: user对象中标识主键的属性名称
                 column: 主键在表中的列名
                 length: 列的数据长度
                 unsaved-value(不常用): 指定主键为什么值时,当做null来处理.
                access(强烈推荐不要用): field 那么在操作属性时,会直接操作对应的字段而不是get/set方法
              -->
            <id name="id" column="id" length="100">
                <!-- generator:主键生成策略
                     1.increment  数据库自己生成主键. 先从数据库中查询最大的ID值,将ID值加1作为新的主键
                    2.identity  依赖于数据的主键自增功能
                    3.sequence    序列,依赖于数据中的序列功能(Oracle).
                    4.hilo(了解) : Hibernate自己实现序列的算法,自己生成主键. (hilo算法 )
                    5.native 自动根据数据库判断,三选一. identity|sequence|hilo
                    6.uuid  生成32位的不重复随机字符串当做主键
                    7.assigned 自己指定主键值. 表的主键是自然主键时使用。-->
                <generator class="identity"></generator>
            </id>
            
            <!-- property : 实体中属性与表中列的对应
                 name : 实体中属性名称
                 column : 表中列的名称
                 length : 数据长度
                 precision: 小数点后的精度
                 scale:    有效位数
                 insert(一般不用): 该属性是否加入insert语句.
                 update(一般不用): 该属性是否加入update语句.
                 not-null : 指定属性的约束是否使用 非空
                 unique : 指定属性的约束是否使用 唯一
             -->
             <!-- 
                 type: 表达该属性的类型
                 可以用三种方式指定属性
                 java类型                  数据库类型指定            Hibernate类型指定
                 java.lang.String     varchar                string
              -->
            <property name="username" column="username" update="true" type="string" ></property>
            <property name="password" column="password"></property>
            <!-- <property name="sal" column="sal" precision="2" scale="3" ></property> -->
         </class>
     </hibernate-mapping>

      测试类

    package com.oy.helloworld;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    import org.junit.Test;
    
    public class TestHelloWorld {
        @Test
        public void fun1() {
            // 读取配置文件
            Configuration conf = new Configuration().configure();
            // 根据配置 创建Factory
            SessionFactory sessionFactory = conf.buildSessionFactory();
            // 通过获得操作数据库的session对象
            Session session = sessionFactory.openSession();
            // 操作数据库
            User u = new User();
            u.setUsername("tom");
            u.setPassword("222");
            session.save(u);
            // 关闭资源
            session.close();
            sessionFactory.close();
        }
    }

      测试结果:控制台打印

    Hibernate: 
        insert 
        into
            user
            (username, password) 
        values
            (?, ?)

      数据库记录插入成功

      需要注意的地方:

      1)hibernate 默认需要手动开启提交事务,也可以配置自动提交事务

    <!-- hibernate.connection.autocommit: 事务自动提交,默认false  -->
    <property name="hibernate.connection.autocommit">true</property>

      2)mysql 引擎 MyISAM 不支持事务,所以如果使用 MyISAM  引擎,事务失效,插入总是成功(不会回滚),也即

    <property name="hibernate.connection.autocommit">false</property> 配置成 false,也会插入成功。

      测试 事务

    <property name="hibernate.connection.autocommit">false</property>

      hibernate.connection.autocommit 配置成 false,事务不会自动提交,插入记录被回滚了

    5、Hibernate-api详解    <--返回目录

    5.1、Configuration对象    <--返回目录

      加载src下名为hibernate.cfg.xml

    Configuration conf = new Configuration().configure();

      如果配置文件不符合默认加载规则,调用

    Configuration conf = new Configuration().configure(File file);//通过file加载
    Configuration conf = new Configuration().configure(String path);//通过路径加载

      可以通过Configuration对象加载映射文件(不推荐)。conf.addClass(User.class);之所以可以这样实现加载,因为有下面规范
              规范1:ORM映射文件名称与实体名称一致;
             规范2:ORM映射文件需要与实体类放在同一包下
            
      推荐使用hibernate.cfg.xml 使用mapping属性引入映射文件

    <mapping resource="com/oy/domain/User.hbm.xml"/>

    5.2、SessionFactory对象    <--返回目录

      创建 Factory

    Configuration conf = new Configuration().configure(); // 读取配置文件
    SessionFactory sessionFactory = conf.buildSessionFactory();


      获取一个全新的 session 对象

    Session session = sessionFactory.openSession();


           
      获得与当前线程绑定的 session 对象,如果没有,获取一个新的 session

    先配置:<property name="hibernate.current_session_context_class">thread</property>  
    将session与线程绑定,只有配置了该参数,才能使用getCurrentSession()
    Session session = sessionFactory.getCurrentSession();

    5.3、Session-增删改    <--返回目录

      增

    User user = new User();
    user.setUname("李四");
    user.setPassword("123");
    session.save(user);

      改

    //先查
    //开启事务
    Transaction ts= session.beginTransaction();
    //
    User _user = (User) session.get(User.class, 1);//取一个User对象,id=1
    System.out.println(_user);
    //
    _user.setPassword("abc"); //修改密码
    _user.setUname("张三");  //修改密码
    session.update(_user);  //执行修改
    //关闭事务
    ts.commit();

      或者

    User user1 = new User();
    user1.setUid(1);  //指定id
    user1.setPassword("def");  //修改密码
    user1.setUname("zhangsan"); //修改用户名
    
    Transaction ts= session.beginTransaction(); //修改操作必须先开启事务
    session.update(user1); //执行修改
    ts.commit();  //提交事务

      删(根据id删除,只有对象有id就行)

    //User _user = (User) session.get(User.class, 1);//取一个User对象,id=1
    User user2 = new User();
    user2.setUid(1);  //指定id
    Transaction ts= session.beginTransaction(); //删除操作必须先开启事务
    session.delete(user2);
    ts.commit();  //提交事务

    5.4、Session-HQL查询    <--返回目录

      HQL语言:Hibernate Query Language
              session.createQuery("HQL语句");


      查询所有
              Query query = session.createQuery("from com.oy.domain.User");
              List<User> userList = query.list();//list()将语句执行,并返回结果

    5.5、Session-Criteria&Sql查询    <--返回目录

      Criteria查询==>Hibernate独创的面向对象的查询==>无语句

    //查询所有
    Criteria criteria = session.createCriteria(User.class);
    List<User> userList = criteria.list();


      原生的sql查询,查询所有

    SQLQuery query = session.createSQLQuery("select * from t_user ");
    query.addEntity(User.class);
    List<User> userList = query.list();

    5.6、session.load()    <--返回目录

     

      问题1:load()方法,返回一个代理对象,获得其内容时,会查询数据库,是每次访问属性都会查询数据库吗?
            答:不是每次都查。代理对象中有一个表识是否被初始化的boolean型变量,记录是否被初始化过。


      问题2:代理都是要基于接口的,用load()方法返回的代理,就没有实现任何接口?
            答:java中的动态代理是基于接口;而Hibernate是使用javassist-3.12.0.GA.jar产生代理对象,
            该代理与被代理对象之间的关系是继承关系。代理对象是被代理对象的子类。

    5.7、Transaction详解    <--返回目录

        * 开启事务 Transaction ts= session.beginTransaction();
        * 提交事务 ts.commit();
          回滚事务 ts.rollback();
        * 获得已经打开的事务对象(很少用)
            session.getTransaction();
        * 事务关闭时,会自动把与当前线程关联的session关闭,并删除

      事务代码规范写法

    Session session = null;
    Transaction tx = null;
    try {
        session = HibernateUtils.openSession();
        tx = session.beginTransaction(); // 开启事务
        // ==============================================
        
        // ==============================================
        tx.commit(); // 提交事务
    } catch (Exception e) {
        tx.rollback(); // 回滚事务
    } finally {
        session.close(); // 关闭操作
    }

    5.8、Query详解    <--返回目录

        * Query对象:封装HQL语句的对象
        * 查询所有
            Query query = session.createQuery("from com.oy.domain.User");
            List<User> userList = query.list();//list()方法将hql句执行,并返回List<User>
        * 查询一条记录
            Query query = session.createQuery("from com.oy.domain.User where uname='张三'");
            User u = (User)query.uniqueResult();//执行hql语句,返回一个User对象
        * 分页 limit Index,count;
            query.setFirstResult(index);//指定结果从第index个取
            query.setMaxResults(count);//指定取几条记录

    5.9、Criteria详解(了解,开发中用得不多)    <--返回目录

        * Criteria查询==>Hibernate独创的面向对象的查询==>无语句
        * 查询所有
            Criteria criteria = session.createCriteria(User.class);
            List<User> userList = criteria.list();
        * 查询一条记录
            Criteria criteria = session.createCriteria(User.class);
            criteria.add(Restrictions.eq("uname","张三"));//查询name=张三的记录
            User u = (User)criteria.uniqueResult();
        * 查询uname字段中包含"三"的记录
            criteria.add(Restrictions.like("uname","%三%"));
            List<User> userList = criteria.list();
        * 查询uid>1的记录
            criteria.add(Restrictions.gt("uid",1));
            List<User> userList = criteria.list();
        * > gt   < lt    = eq    >=ge    <=le    like      between

    5.10、封装Hibernate工具类    <--返回目录

    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    public class HibernateUtils {
        // 会话工厂,整个程序只有一份。
        private static SessionFactory sf;
    
        static {
            // 1 加载配置
            Configuration config = new Configuration().configure();
    
            // 2 获得工厂
            sf = config.buildSessionFactory();
            // 3 关闭虚拟机时,释放SessionFactory
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
                public void run() {
                    System.out.println("虚拟机关闭!释放资源");
                    sf.close();
                }
            }));
        }
    
        // 获得一个新的session
        public static Session openSession() {
            return sf.openSession();
        }
    
        // 获得当前线程中绑定session
        public static Session getCurrentSession() {
            return sf.getCurrentSession();
        }
    }
    View Code

    6、Hibernate-配置文件    <--返回目录

      hbm2ddl
           * <property name="hbm2ddl.auto">create</property>
            - update:最常用,如果当前数据库中不存在表结构,自动创建表结构;如果存在表结构,并且表结构与实体一致,那么不做修改;
                     如果存在表结构,并且表结构与实体不一致,那么会修改表结构,会保留原有列。
            - create(很少用):无论是否存在表结构,每次启动Hibernate都会重新创建表结构(数据会丢失)。
            - create-drop(很少用):无论是否存在表结构,每次启动Hibernate都会重新创建表结构;运行结束时删除表。
            - validate(很少用):不会自动创建表结构,也不会自动维护表结构,只会校验表结构。如果表结构不一致,抛出异常。

      方言    
           * <property name="hibernate.dialect">org.hibernate.dialect.MySqlDialect</property>

    7、Hibernate-实体配置详解-实体规则    <--返回目录

        * 实体编写规则
            - 提供一个无参数 public访问控制符的构造器
            - 提供一个标识属性,映射数据表主键字段
            - 所有属性提供public访问控制符的 set  get 方法(javaBean)
            - 标识属性应尽量使用基本数据类型的包装类型
                ** 基本数据类型和包装类型对应hibernate的映射类型相同
                ** 基本类型无法表达null、数字类型的默认值为0。
                ** 包装类默认值是null。当对于默认值有业务意义的时候需要使用包装类。
            - 不要用final修饰实体 (将无法生成代理对象进行优化)
                ** 生成代理对象,代理对象是被代理对象的子类,final类不能被继承
        * 持久化对象的唯一标识-oid&主键
            - 关系数据库用主键区分同一条记录
            - Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系
            - 结论: 对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID赋值
        * 区分自然主键和代理主键
            - 主键需要具备: 不为空/不能重复/不能改变
            - 自然主键:    在业务中,某个属性符合主键的三个要求。那么该属性可以作为主键列。
            - 代理主键: 在业务中,不存符合以上3个条件的属性,那么就增加一个没有意义的列作为主键。

    8、映射文件详解    <--返回目录

        * <hibernate-mapping package="com.oy.d_hbm">
          <class name="User" table="t_user"> 
          配置了package属性,则User前面无需加包名
       
        * <class name="com.oy.d_hbm.User" table="t_user">
            - 属性dynamic-insert:动态插入,默认为false,true=>如果字段为null,不参与insert语句
            - 属性dynamic-update:动态修改,默认为false,true=>如果字段为null,不参与update语句
       
        * <id name="uid" column="uid">
            - 属性length:修改表uid的数据长度,演示不成功
            - unsaved-value(不常用):指定主键为什么值时,当做null来处理
                ** 我们建实体类的规则,主键使用包装类
            - access(不推荐使用):field,那么在操作属性时,直接操作对应的字段,而不是get/set方法
        * 主键生成策略
            <id name="uid" column="uid">
                <!-- 主键生成策略:native表示由数据库维护主键(数据库中主键设置为自增) -->
                <generator class="native"></generator>
            </id>
           
            - <generator class="">主键生成策略
            - 1)increment:数据库自己生成。先从数据库总查询最大的ID值,将ID值加1
                ** 当主键生成策略为increment,save()方法会使用语句select max(uid) from t_user来给user设置uid;
                ** save()方法不会使用insert语句;
                ** 此时,需要使用事务提交,才会使用insert语句,把数据持久化到数据库中;
            - 2)identity:依赖数据的主键自增功能
                ** 当主键生成策略是identity,save()方法使用insert语句获取uid;
                ** 由于使用了insert语句,save()方法后数据已经持久化到数据库中了;
            - 3)sequence:序列,依赖于数据中的序列功能(Oracle)
            - 4)hilo(了解,永远用不到):Hibernate自己实现序列的算法,自己生成主键,hilo算法
            - 5)native:自动根据数据库判断,identity, sequence, hilo三选一
            - 6)uuid:生成不重复的32位随机字符串当做主键
            - 7)assigned:自己设置主键值。一般在表的主键是自然主键时使用该策略。
           
        * 实体其他属性<property name="" column=""></property>
            - length:数据长度
            - precision:小数点后的精度,(字段为double类型时使用)
            - scale:有效位数,(字段为double类型时使用)
            - insert(一般不用):false表示该属性是否加入inset语句
            - update(一般不用):false表示该属性是否加入update语句
            - not-null:知道属性的约束是否使用非空
            - unique:指定属性的约束是否使用唯一
            - type:表达该属性的类型,可以使用三种方式来指定属性
                java类型             数据库类型             Hibernate类型
            java.lang.String      varchar                   string

    ---

  • 相关阅读:
    sipp3.6对freeswitch进行压力测试
    随机四则运算
    大一暑假第八周周进度总结报告
    大一暑假第七周周进度总结报告
    学生信息管理系统java测试报告
    原码、反码、补码解读
    大一暑假第六周周进度总结报告
    01Java方法
    00java语法基础和课后实践
    验证码和判断回文(递归)
  • 原文地址:https://www.cnblogs.com/xy-ouyang/p/13111617.html
Copyright © 2020-2023  润新知