zoukankan      html  css  js  c++  java
  • Hibernate框架_1 单表映射 _2

    2017/03/22
    hibernate常用配置:注意:hibernate前缀可以省略
    注释符号:<!-- context -->
    hibernate.show_sql:是否把hibernate运行时的SQL语句输出到控制台,编码阶段便于测试。
    hibernate.format_sql:输出到控制台的SQL语句是否进行排版,便于阅读。建议设TRUE。
    hbm2ddl.auto:表结构生成策略。可帮助由java代码生成数据库脚本,进而生成具体的表结构。
     create(表结构存在,先删除,再重新创建)|update(在原有表结构中插入)|create-drop(先创建再删除)|validate(验证表结构,如现在结构与原结构不同,则不会创建表结构)
    hibernate.default_schema:默认的数据库。执行SQL时,默认给所有表名加上数据库前缀
    hibernate.dialect:配置hibernate数据库方言,hibernate可针对特殊数据库进行优化。

    ====================================

     session简介


    开启一个一个session必须开启一个事务,所以session封装在事务(transaction)中。
    session:可理解为session是一个数据库操作对象。
    session与connection,是多对一关系,每个session都有一个与之对应的connection,一个connection不同时刻可提供多个session使用。

    把对象保存在关系数据库中需要调用session的各种方法:
    如:
    save(),update(),delete(),createQuery()等。

     =====================================================

    transaction简介:事务
    ·hibernate对数据的操作都是封装在事务当中,并且默认是非自动提交的方式。
     所以用session保存对象时,如果不开启事务,并且手工提交事务,对象并不会真正保存在数据库中。
    ·如果想让hibernate想jdbc那样自动提交事务,必须调用session对象的doWork()方法,活得jdbc的connection后,设置其为自动提交事务模式。(注意:通常并不推荐这样做)
    --自动提交事务(注意:通常并不推荐这样做)---
    //不开启事务(transaction.commit()//提交事务)的方式
     @Test
     public void testSaveStudents(){
      Stusdents s= new Students(1,"ZSF",new Date(),"wudang");
      session.doWork(new Work(){
     @Override
     public void execute(Connection connection) throws SQLException{
       connection.setAutoCommit(true);
     }
      })

      session.save(s);//保存对象进入数据库
      session.flush();//强制发出SQL语句(通过SQL写入SQL)
     }
    ---自动提交事务(注意:通常并不推荐这样做)---

    private Transaction transaction;

    transaction  = session.beginTransaction();//打开事务
    transaction.commit()//提交事务

    =============================================

    session详解
    ·如何获得session对象?
    1)openSession
    2)getCurrentSession
    如果使用getCurrentSession需要在hibernate.cfg.xml文件中进行配置:
    如果是本地事务(jdbc事务)
     <property name="hibernate.current_session_context_class">thread</property>
    //本次说明不涉及全局事务
    如果是全局事务(jta事务)
     <property name="hibernate.current_session_context_class">jta</property>
    ·
    @Test  //org.junit.test包
     public void testOpenSession(){
      
      Configuration config = new Configuration().configure();// 创建配置对象
      ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()applySettings(config.getProperties()).buildServiceRegistry();//创建服务注册对象
      SessionFactorysessionFactory  = conf.buildSessionFactory(serviceRegistry );//创建会话工厂对象
      Session session = serviceRegistry .openSession();//打开会话
      IF(session != null)
      {
         System.out.println("create session success!");
      }
     }

    配置文档:<property name="hibernate.current_session_context_class">thread</property>追加

    @Test  //org.junit.test包
     public void testgetCurrentSession(){
      
      Configuration config = new Configuration().configure();// 创建配置对象
      ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()applySettings(config.getProperties()).buildServiceRegistry();//创建服务注册对象
      SessionFactorysessionFactory  = conf.buildSessionFactory(serviceRegistry );//创建会话工厂对象
      Session session = serviceRegistry.getCurrentSession();//获得当前会话
      IF(session != null)
      {
         System.out.println("get current session success!");
      }
     }

     =========================================

    ·openSession 区别getCurrentSession
    1)getCurrentSession在事务提交或者回滚之后会自动关闭,而openSession需要手动关闭。
       如果使用openSession而没有手动关闭,多次之后会导致连接池溢出。

     @Test  //org.junit.test包
     public void testgetCurrentSession(){
      
      Configuration config = new Configuration().configure();// 创建配置对象
      ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()applySettings(config.getProperties()).buildServiceRegistry();//创建服务注册对象
      SessionFactorysessionFactory  = conf.buildSessionFactory(serviceRegistry );//创建会话工厂对象
      Session session1 = serviceRegistry.openSession();//获得当前会话
      Transaction transaction = session1.beginTransaction();
      Students s= new Students(1,"jo","male","bejing")
      session1.doWork(new Work(){
     @Override
     public void execute(Connection connection) throws SQLException{
       System.out.println("hashCode!"+connection.hashCode;);
     }
      })
      session1.save(s);
      transaction.commit();
      //session1.close();
      Session session2 = serviceRegistry.openSession();//获得当前会话
      Transaction transaction = session2.beginTransaction();
      Students s= new Students(2,"jon","female","shanghai")
      session2.doWork(new Work(){
     @Override
     public void execute(Connection connection) throws SQLException{
       System.out.println("hashCode!"+connection.hashCode;);
     }
      })
      session2.save(s);
      transaction.commit();
      //session2.close();

     }
     结果:两次hashCode不同,证明是两个链接
     getCurrentSession()则两次hashCode相同

    2)openSession 每次创建新的对象,getCurrentSession使用现有的session对象(单例模式)。
       Session session1 = serviceRegistry.openSession();
       Session session2 = serviceRegistry.openSession();
     System.out.println(session1==session2);//console ->false
       Session session1 = serviceRegistry.getCurrentSession();
       Session session2 = serviceRegistry.getCurrentSession();
     System.out.println(session1==session2);//console ->true

    =============================================

    hbm配置文件常用设置
    hbm.xml配置文档

    <hibernate-mapping<br>
     schema="schemaName" //模式的名字
     catalog="catalogName" //目录的名称
     default-cascade="cassade_style" //级联风格
     default-access="field/property/CalssName" //访问策略
     default-lazy="true/false" //加载策略
     package="packagename" //默认包名
    />

    <class<br>
     name="ClassName" //对应映射的类<br>
     table="tableName" //对应映射数据库的表<br>
     batch-size="N" //抓取策略,一次抓取多少记录<br>
     where="condition" //条件 eg:抓取条件<br>
     entity-name="EntiyName" //如果需要映射多张表<br>
    />
    //表的主键
    <id
     name="propertyName" //对应的属性
     type="typeName" //对应类型
     column="column_nam" //映射数据库中表当中字段名的名称
     length="length" //指定长度
     <generator class="generatorClass"/>//主键生成策略
    </id>
    主键生成策略:
    由于使用MYSQL,着重讲解一下两个
    native:有底层数据库自动生成标识符
    assigned:手工赋值
    1、代理主键:是指与业务无关且能唯一标识数据库中记录,一般是数据库自动生成的,比如mysql可以使用auto_increment,Sql2000可以使用identity生成方式,oracle可以使用sequence生成方式。<br>
    2、自然主键:指业务相关,由用户指定,且能唯一标识数据库中的任意一条记录。

    ================================================
    hibernate单表操作-单一主键

    duplicate美 [ˈdu:plɪkeɪt]v. 重复;复制 adj.复制的;副本的;完全一样的
         n.副本;完全一样的东西 ;复制品

    单一主键:表当中某一列column充当主键
    assigned 由Java应用程序负责生成(手工赋值)。
    native 有底层数据库自动生成标识符。
            如果是MySQL就是increment(自动增长类型,注:自动增长类型手动赋值不起作用),如果是Oracle就是sequence(序列) 等等。

    ================================================
    hibernate单表操作-基本类型


    date
    timestamp(时间戳)

     Students.hbm.xml
    <hibernate-mapping>
      <class>
        <id name = "sid" type="int">//主键
     <column name = "SID"/>
     <!--<generator class="assigned"/>-->
     <generator class="native"/>//主键生成策略:
        </id>
        <property name="brithday" type = "date"></property>
      </class>
    </hibernate-mapping>
    type :java.util.Date  ->数据库:YYYY-MM-DD HH:MM:SS
    type :timestamp(hibernate映射类型)  ->数据库:YYYY-MM-DD HH:MM:SS
    type : date(hibernate映射类型)->数据库:YYYY-MM-DD
    type : time(hibernate映射类型)->数据库:HH:MM:SS

    ================================================
    hibernate单表操作-对象类型

    hibrnate映射类型

    java类型 标准SQL类型 MYSQL类型 Oracle类型
    binary byte[] VARCHAR(或BLOB) BLOB BLOB
    text java.lang.String CLOB TEXT CLOB
    clob java.sql.Clob CLOB TEXT CLOB
    blob java.sql.Blob BLOB BLOB BLOB

    text,clob:大文本数据类型

    blob:二进制数据类型,如音频视频图片。

    注意:Mysql不支持标准SQL的CLOB类型,在Mysql中,

    用TEXT(短文本),MEDIUMTEXT(中长文本)及LONGTEXT类型来表示长度超过255的长文本数据。

    1)在students.java中加入BLOB类型字段

    private Blob picture;

    2)add setter and getter

    3)  a. Students.hbm.xml删除(需要重新生成)

         b. Students.hbm.xml重新生成:src(students.java 所在folder)/new/other/Hibernate XML Mapping file(hbm.xml)

    <property name="brithday" type = "java.sql.Blob"></property>

    @Test

    public void testWriteBlog() throws Exception{

      Student s= new Students();

      //get picture

      File f= new File("d:"+File.separator+"boy.jpg");

          InputStream input = new FileInputStream(f);

      //创建Blob

      Blob image = Hibernate.getLobCreator(session).createBlob(input,input.available());

      //设置照片属性,保存

      s.setPicture(image);

          session.save(s);

    }

    @Test 注意 读取时,表策略改成update(create会先清空表结构,数据就没有了)

    public void testReadBlog() throws Exception{

      Student s= (Students)session.get(Students.class,1);

      //get picture

      

      Blob image =  s.getPicture()

      //照片输入流

          InputStream input = image.getBinaryStream();

      //创建输出流

      File f= new File("d:"+File.separator+"dest.jpg");

      OutputStream output = newFileOutputStream(f);

      //创建缓冲区

      byte[] buff = new byte[input.available()];

      input.read(buff);

          output.write(buff);

      input.close();

      output.close();

    }

    }

    ================================================
    hibernate单表操作-组件属性

    ·实体类中的某个属性属于用户自定义的类的对象。

    组件属性

    如果持久化类的属性并不是基本数据类型,也不是一个日期或者字符串常量,而是一个复合类型的对象,例如 private Name name; 那么这就是一个组件属性。

    组件属性可以是任何普通的java类对象,在映射文件中则用<compent>标签标识,<compent>中又可以像<class>那样包含<property>子元素,此外<compent>中还可以包含一个<parent>子元素用来指向容器实体。

    下面演示组件属性的用法,比如在Person持久化类中有一个Name属性

    参看http://www.cnblogs.com/fysola/p/6248579.html

     public class Address{

      private String postcode;

      private String phonenumber

      private String address

      public Address(){

      //getter setter

      //toString

      }

    }

    public class Students{

      property...

      //private String address;

      private Address address;

    }

    //<property name = "address" type ="java.sql.Blob" ><

    //  column ="ADDRESS"/>

    //<property>

    <compent name= "address" type = "Address">

      <property name = "postcode" column ="POSTCODE"/>

      <property name = "phonenumber" column ="PHONENUMBER"/>

      <property name = "address" column ="ADDRESS"/>  

    </compent>

    ================================================
    hibernate单表操作-单表CRUD操作实例

    使用的session方法:save,update,delete,get/load(查询单个记录)

    ·get与load的区别:

     1)在不考虑缓存的情况下,get方法会在调用之后立即向数据库发出sql语句,返回持久化对象。

      load方法会在调用后返回一个代理对象。该代理对象只是实体对象的id(主键),

      直到使用非主键属性时才会发出SQL语句。

        2)查询数据库不存在的数据时,get返回null,

         load跑出异常org.hibernate.ObjectNotFoundException.

    查询测试:

    @Test 生成策略需要为update(create会被清空)

    public void testGetStudents {

      Students s = (Students)session.get(Students.class,100)//使用反射得到类型+主键

      System.out.printlin(s);

    }

    @Test

    public void testLoadStudents {

      Students s = (Students)session.load(Students.class,100)//使用反射得到类型+主键

      System.out.printlin(s);

    }

    @Test

    public void testUpdateStudents {

      Students s = (Students)session.get(Students.class,100)//使用反射得到类型+主键

      s.setGender("女");

      session.update(s);

    }

    @Test

    public void testDeleteStudents {

      Students s = (Students)session.get(Students.class,100)//使用反射得到类型+主键

      session.delete(s);

    }

  • 相关阅读:
    海量数据库及分区4——《12年资深DBA教你Oracle开发与优化——性能优化部分》
    海量数据库及分区4——《12年资深DBA教你Oracle开发与优化——性能优化部分》
    高级SQL优化(三) 常用优化工具 ——《12年资深DBA教你Oracle开发与优化——性能优化部分》
    海量数据库及分区2——《12年资深DBA教你Oracle开发与优化——性能优化部分》
    海量数据库及分区1——《12年资深DBA教你Oracle开发与优化——性能优化部分》
    高级SQL优化(三) 常用优化工具 ——《12年资深DBA教你Oracle开发与优化——性能优化部分》
    实习生招聘笔试
    海量数据库及分区1——《12年资深DBA教你Oracle开发与优化——性能优化部分》
    高级SQL优化(一) ——《12年资深DBA教你Oracle开发与优化——性能优化部分》
    海量数据库及分区2——《12年资深DBA教你Oracle开发与优化——性能优化部分》
  • 原文地址:https://www.cnblogs.com/charles999/p/6598273.html
Copyright © 2011-2022 走看看