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);

}

原文地址:https://www.cnblogs.com/charles999/p/6598273.html