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