Hibernate一 入门
一 简介
1.什么是ORM
Object/Relation Mapping,即对象/关系映射。可以将其理解为一种规范,具体的ORM框架可以作为应用程序和数据库的桥梁。面向对象程序设计语言与关系数据库发展不同步时,需要一种中间解决方案,而ORM就是这样的解决方案 。ORM工具的唯一作用就是:把对持久化对象的保存、删除、修改等操作,转换成对数据库的操作。
ORM并不是一种具体的产品,而是一类框架的总称,它概述了这类框架的基本特征:完成面向对象的程序设计语言到关系数据库的映射。
基于ORM框架完成映射后,既可以利用面向对象程序设计语言的简单易用性,又可以利用关系数据库的技术优势。
目前ORM的产品非常多,如Apache组织的QIB,Oracle的TopLink,JDO,JPA等等。
2.Hibernate
Hibernate是目前最流行的ORM框架之一,它是一个面向Java环境的对象/关系数据库映射工具
它也是一个轻量级的O/R Mapping框架,是目前最流行的持久层解决方案,较之另一个持久层框架MyBATIS,更具有面向对象的特征
Hibernate是ORM规范的实现框架,所有的ORM框架的作用:负责把面向对象的持久化操作,转化为数据库标准SQL语句去执行
但是Hibernate不一定能提高程序的性能,可扩展性和可维护性
ORM规范映射思想:一个表映射成一个类;一行记录(一条数据)映射成一个对象,一列(一个字段)映射成对象的属性
3.下载:www.hibernate.org/downloads
解压后的文档结构如下:
documentation:各种相关的文档,包括Hibernate的参考文档和API文档等等
lib:存放了核心类库以及编译和运行所依赖的第三方类库。其中lib路径下的required子目录下保存了运行Hibernate的核心类库,以及必需的第三方类库
project:存放了Hibernate各种相关项目的源代码
lgpl.txt、logo等杂项文件
二 具体实现
1.PO(持久化对象)
Person.class
public class Person {
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", password=" + password
+ ", birthday=" + birthday + "]";
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPassword() {
return password;
}
public void setPassword(int password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
private Integer id;
private String name;
private int password;
private Date birthday;
public Person() {
super();
}
public Person(String name, int password, Date birthday) {
super();
this.name = name;
this.password = password;
this.birthday = birthday;
}
}
如上所示,Hibernate采用了POJO(普通的、传统的Java对象)作为持久化类,这就是Hibernate被称为低侵入式设计的原因。Hibernate不要求持久化类继承任何父类,或者实现任何接口,这样可以保证代码不被污染。
注意:持久化设计时持久化类通常建议使用一个持久化标识符(ID),并且建议使用封装类(基本类型有默认值)。通常要给定一个无参构造器,因为有些操作是反射进行的,属性通常要提供getter/setter方法,持久化类不能是final类型。持久化类中如果使用了集合类型数据,只能使用接口类型进行声明(List,Set,Map),如:List list=new ArrayList();
如何将一个POJO转换为PO呢?也就是说如何将上面的Person类进行持久化呢?Hibernate提供了三种方式:
(1)使用持久化注解(以JPA标准注解为主)
(2)使用JPA提供的xml配置文件,很少使用
(3)使用Hibernate传统的xml映射文件(*.hbm.xml文件的形式)
这里使用第一种和第三种方法作为示例
a.建立Person.hbm.xml
该文件是一个持久化映射文件,将Java对象映射到数据库表。几乎所有的ORM工具都需要一个数据库字段与JavaBean属性匹配的映射文件,在hibernate中一般命名为*.hbm.xml
<?xml version="1.0"? >
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping >
//name指定需要持久化的类(包加类名),table指定需要映射的表名
<class name="HibernateTest.Person" table="t_person"> <!-- 类对应到数据库中的表 -->
<id name="id"> <!-- Person类中的id为class的id,id必须指定,name指定持久化类的持久化标识符名称,generate指定id生成策略-->
<generator class="native"></generator> <!-- 该id为本地产生 -->
</id>
<property name="name" column="t_name"></property>
<property name="password" length="6"></property>
<property name="birthday"></property>
</class>
</hibernate-mapping>
注意:在xml文件中,name对应的是java类中的对象,property为其他属性映射配置,name为持久化类中需要映射的属性名,column指定表的列名(不写表示默认使用属性名),length指定列存储数据长度,type指定字段类型
b.使用持久化注解
将Person.java修改为:
@Entity
@Table(name="t_person")
public class Person {
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", password=" + password
+ ", birthday=" + birthday + "]";
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPassword() {
return password;
}
public void setPassword(int password) {
this.password = password;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@Column(name="t_name")
private String name;
@Column(length=6)
private int password;
private Date birthday;
public Person() {
super();
}
public Person(String name, int password, Date birthday) {
super();
this.name = name;
this.password = password;
this.birthday = birthday;
}
}
其中,@Entity注解声明该类是一个持久化类,@Table指定该类映射的表,@Id指定该类的标识属性,@GeneratedValue指定主键生成策略,@Column用于指定数据库中对应列的详细信息。由此可见,PO=POJO+持久化注解
2.Hibernate配置文件
在生成PO文件后,就要在hibernate.cfg.xml中配置各种信息。
hibernate的project->etc中有各种模板,将其中的hibernate.cfg.xml复制到项目的src路径中。在这里展示一下mySQL数据库的连接方式:
<hibernate-configuration>
<session-factory>
//配置成数据库方言模式,更方便数据库识别
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///mydb</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
//数据库连接池
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.min_size">1</property>
<property name="hibernate.c3p0.timeout">5000</property>
//根据需要自动创建数据库表
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<property name="hibernate.format_sql">true</property>
//这个是Person.hbm.xml对应的配置
<mapping resource="HibernateTest\Person.hbm.xml"></mapping>
//这个对应的是持久化注解的PO类的路径
<mapping class="HibernateTest.Person"></mapping>
</session-factory>
</hibernate-configuration>
注意:各种数据库的连接方式可以具体在hibernate.properties.template文件查找,该文件都有详细的定义。其中,mapping根据PO持久化的方式有两种选择。
hibernate通过C3P0数据源来管理数据库连接,当程序创建数据源实例时,系统会一次性创建多个数据库连接,并将这些数据库连接保存在连接池中。程序访问数据库时,直接从连接池中取出一个空闲的数据库连接;访问结束后,无需关闭数据库直接将连接还给连接池即可。通过这种方式,可以避免频繁的获取数据库连接、关闭数据库连接所导致的性能下降。将optional路径下的C3P0的JAR包导入项目路径下。
其中,<property name="hibernate.hbm2ddl.auto">update</property>,update表示程序启动时没有就创建表,有就检查有没有更新(推荐使用)
3.编写测试程序test.java
public class test {
public static void main(String[] args) {
//创建Configuration实例,并加载配置文件(hibernate.cfg.xml),唯一的作用是创建SessionFactory,一旦创建完成就被丢弃
Configuration config=new Configuration().configure();
SessionFactory factory=config.buildSessionFactory();
Session session=factory.openSession();
Transaction tx=session.beginTransaction();
Person p=new Person(123,"admin",123456,new java.util.Date());
//将Person对象持久化到数据库
session.save(p);
//事务提交
tx.commit();
session.close();
//关闭SessionFactory,通常不用手动关闭
factory.close();
}
}
结果:
Hibernate:
create table t_person (
id integer not null auto_increment,
t_name varchar(255),
password integer,
birthday datetime,
primary key (id)
) ENGINE=InnoDB
Hibernate:
insert
into
t_person
(t_name, password, birthday)
values
(?, ?, ?)
同时数据库中建立了一个表为t_person,字段分别为id(1),t_name(admin),password(123456),birthday(...)
三 Hibernate的体系结构
1.SessionFactory
这是Hibernate的关键对象,它是单个数据库映射关系经过编译后的内存镜像,是线程安全的。应用程序从SessionFactory中获得Session实例,它在多个线程间进行共享。通常情况下,整个应用只有唯一的一个会话工厂。但是如果访问多个数据库,就需要对每一个数据库使用一个会话工厂。会话工厂缓存了生成的SQL语句和hibernate在运行时使用的映射元数据。
2.Session
它是应用程序与持久存储层之间交互操作的一个单线程对象,所有的PO必须在Session管理下才可以进行持久化操作。
生存期很短,底层封装了JDBC连接,也是Transaction的工厂。
Session有一个必选的一级缓存,显式执行flush之前,所有持久化操作都在缓存中。
3.Transaction
代表一次原子操作,具有数据库事务的概念。将应用代码从底层的事务实现中抽象出来,这可能是一个JDBC事务,一个JTA用户事务或是一个公共对象请求代理结构(CORBA),允许应用通过一组一致的API控制事务边界。这有助于保持Hibernate应用在不同类型的执行环境或容器中的可移植性。使用Hibernate进行操作(增删改)必须显示的调用它,即必须要commit。
整个的逻辑结构为:
业务逻辑层:业务对象(对象、属性、关联、继承)-->Person.java
持久化层: ORM API/ORM 实现-->Person.hbm.xml
JDBC-->hibernate.cfg.xml
数据库层:关系型数据库
四 改变持久化对象状态的方法
1.持久化实体
包括save()和persist()两种方法,如:
Person p=new Person();
p.setName("lyy");
session.save(p);
save()与persist()方法的区别:使用save()方法时会返回该持久化对象的标识属性值,即主键值;使用persist()方法时,不会返回任何值。程序执行save()方法会立即将持久化对应的数据插入到数据库,而persist()方法则保证当它在一个事务外部被调用时,并不立即转换成insert语句,在需要封装一个长会话时,这个方法尤为重要。
2.根据主键加载持久化类
主要包括load()和get()方法,如:
Person p=session.load(Person.class,1);
load()和get()的区别:主要区别在于是否延迟加载。load()方法具有延迟加载功能,Load()不会立即访问数据库,当试图加载的记录不存在时,可能返回一个未初始化的代理对象;而get()方法总是立即访问数据库,当记录不存在时,直接返回null
3.更新持久化实体
Person p=session.load(Person.class,1);
p.setPassword("345345");
也就是说,使用load()方法后就可以直接对实体进行更新。
4.使用saveOrUpdate()
saveOrUpdate()表示新增或更新,若id存在就是更新,不存在就报更新失败;如果不给id,就是新增
public class test {
private static void testSaveOrUpdate(){
Configuration config=new Configuration().configure();
SessionFactory factory=config.buildSessionFactory();
Session session=factory.openSession();
Transaction tx=session.beginTransaction();
Person p=new Person();
p.setId(3);
p.setPassword(12344);
session.saveOrUpdate(p);
tx.commit();
session.close();
}
public static void main(String[] args) {
testSaveOrUpdate();
}
}
修改成功后,密码为12344,其他为空
5.使用merge()
public class test {
private static void merge(){
Configuration config=new Configuration().configure();
SessionFactory factory=config.buildSessionFactory();
Session session=factory.openSession();
Transaction tx=session.beginTransaction();
Person p=(Person)session.get(Person.class, 3);
p.setName("lyy");
Person p2=(Person)session.merge(p);
p2.setBirthday(new java.util.Date());
tx.commit();
session.close();
}
public static void main(String[] args) {
merge();
}
}
注:持久化状态对象会在session关闭的时候如果内存数据和表数据不一致,将自动同步到数据库表
或者:
private static void testSaveOrUpdate(){
Configuration config=new Configuration().configure();
SessionFactory factory=config.buildSessionFactory();
Session session=factory.openSession();
Transaction tx=session.beginTransaction();
Person p=new Person();
p.setId(3);
p.setName("kui");
session.merge(p);
tx.commit();
session.close();
}
结果:name为kui,其他为空,相当于update
6.删除有两种方法:
删除持久化状态对象:
public class test {
public static void main(String[] args) {
Configuration config=new Configuration().configure();
SessionFactory factory=config.buildSessionFactory();
Session session=factory.openSession();
Transaction tx=session.beginTransaction();
Person p=(Person)session.load(Person.class,3);
session.delete(p);
tx.commit();
session.close();
}
}
删除临时化状态对象:
public static void main(String[] args) {
Configuration config=new Configuration().configure();
SessionFactory factory=config.buildSessionFactory();
Session session=factory.openSession();
Transaction tx=session.beginTransaction();
Person p=new Person();
p.setId(4);
session.delete(p);
tx.commit();
session.close();
}
使用junit进行测试:
在项目中new->Junit Test Case->选中setUp()和tearDown()方法,即初始化和最后的资源释放
public class myTest {
SessionFactory factory=null;
Session session=null;
Transaction tx=null;
@Before
public void setUp() throws Exception {
System.out.println("---初始化数据---");
Configuration config=new Configuration().configure();
factory=config.buildSessionFactory();
session=factory.openSession();
tx=session.beginTransaction();
}
@After
public void tearDown() throws Exception {
System.out.println("---释放资源---");
if(session.isOpen()){
session.close();
}
}
@Test
public void test() {
Person p=new Person(2,"admin",123,new Date());
session.persist(p);
tx.commit();
}
}
run as junit test->查看结果
Hibernate一 入门的更多相关文章
- Hibernate从入门到精通(十一)多对多双向关联映射
上次我们在中Hibernate从入门到精通(十)多对多单向关联映射讲解了一下多对多单向关联映射,这次我们讲解一下七种映射中的最后一种多对多双向关联映射. 多对多双向关联映射 按照我们之前的惯例,先看一 ...
- Hibernate从入门到精通(十)多对多单向关联映射
上一篇文章Hibernate从入门到精通(九)一对多双向关联映射中我们讲解了一下关于一对多关联映射的相关内容,这次我们继续多对多单向关联映射. 多对多单向关联映射 在讲解多对多单向关联映射之前,首先看 ...
- Hibernate从入门到精通(九)一对多双向关联映射
上次的博文Hibernate从入门到精通(八)一对多单向关联映射中,我们讲解了一下一对多单向映射的相关内容,这次我们讲解一下一对多双向映射的相关内容. 一对多双向关联映射 一对多双向关联映射,即在一的 ...
- Hibernate从入门到精通(八)一对多单向关联映射
上次的博文Hibernate从入门到精通(七)多对一单向关联映射我们主要讲解了一下多对一单向关联映射,这次我们继续讲解一下一对多单向映射. 一对多单向关联映射 在讲解一对多单向关联之前,按照我们的惯例 ...
- Hibernate从入门到精通(七)多对一单向关联映射
上次的博文Hibernate从入门到精通(六)一对一双向关联映射中我们介绍了一下一对一双向关联映射,本次博文我们讲解一下多对一关联映射 多对一单向关联映射 多对一关联映射与一对一关联映射类似,只是在多 ...
- Hibernate从入门到精通(六)一对一双向关联映射
在上次的博文Hibernate从入门到精通(五)一对一单向关联映射中我们讲解了一下一对一单向关联映射,这次我们继续讲解一下与之对应的一对一双向关联映射. 一对一双向关联 与一对一单向关联映射所不同的的 ...
- Hibernate从入门到精通(五)一对一单向关联映射
上次的博文中Hibernate从入门到精通(四)基本映射我们已经讲解了一下基本映射和相关概念,接下来我们会讲稍微复杂点的映射——关系映射. 关系映射分类 关系映射即在基本映射的基础上处理多个相关对象和 ...
- Hibernate从入门到精通(四)基本映射
映射的概念 在上次的博文Hibernate从入门到精通(三)Hibernate配置文件我们已经讲解了一下Hibernate中的两种配置文件,其中提到了两种配置文件的主要区别就是XML可以配置映射.这里 ...
- Hibernate从入门到精通(三)Hibernate配置文件
在上次的博文Hibernate从入门到精通(二)Hibernate实例演示我们已经通过一个实例的演示对Hibernate的基本使用有了一个简单的认识,这里我们在此简单回顾一下Hibernate框架的使 ...
- Hibernate从入门到精通(二)Hibernate实例演示
上篇Hibernate从入门到精通(一)JDBC简介,我们主要对JDBC进行了简单介绍和使用说明,这次我们做一个Hibernate简单实例,通过这个实例对比Hibernate和JDBC,了解Hiber ...
随机推荐
- 40个DBA日常维护的SQL脚本--1113
from itpub --1.查询碎片程度高的表--条件为什么block>100,因为一些很小的表,只有几行数据实际大小很小,但是block一次性分配就是5个(11g开始默认一次性分配1M的bl ...
- 关于SQL配置管理器的服务无法启动的解决办法!
由于各种问题的因素,导致SQL服务无法启动,然后去事件查看器里看了下,有两个关于SQL 的错误.分别是实例中master.mdf和master.ldf的文件系统拒绝访问! 为了赶作业,带着焦急的心情去 ...
- jQuery 效果- 动画
jQuery animate() 方法允许您创建自定义的动画. jQuery 动画实例 jQuery jQuery 动画 - animate() 方法 jQuery animate() 方法用于创建自 ...
- swfupload上传文件问题
如果你的框架用到了struts2的话 可能会造成request冲突 那么解决的办法就是把该request排除出去 不让struts2拦截
- 浅说prop与attr的区别
jquery中attr和prop的区别 在高版本的jquery引入prop方法后,什么时候该用prop?什么时候用attr?它们两个之间有什么区别?这些问题就出现了. 关于它们两个的区别,网上的答 ...
- 简单实现tab标签页切换
常见面试题: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UT ...
- PHP随机生成指定时间段的指定个数时间
/** * 生成某个范围内的随机时间 * @param <type> $begintime 起始时间 格式为 Y-m-d H:i:s * @param <type> $endt ...
- Sass学习
1.1下载地址: http://rubyinstaller.org/downloads 2.1 安装 SASS是Ruby语言写的,但是两者的语法没有关系.不懂Ruby,照样使用.只是必须先安装Ruby ...
- TatukGIS - GisDefs - ColorToHSL 过程
过程名称 ColorToHSL 所在单元 GisDefs 过程原型 procedure ColorToHSL(const _color: TColor; var _h: Rea ...
- Lua 5.1 for Delphi 2010
This is a Lua 5.1 Wrapper for Delphi 2009 and Delphi 2010 which automatically creates OOP callback f ...