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 ...
随机推荐
- JavaMail API 1.4.7邮件发送
下载oracle javaMail API: http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive- ...
- javascript——面向对象程序设计(3)
<script type="text/javascript"> //1.结合使用构造函数模式和原型模式 //2.动态原型模式 //3.寄生构造函数模式 //4.稳妥构造 ...
- web版扫雷小游戏(二)
接上篇~~第一次写这种技术博客,发现把自己做的东西介绍出来还是一件脑力活,不是那么轻松啊,好吧,想到哪写到哪,流水记录之,待完成之后再根据大家的意见进行修改吧. 游戏实现 根据对扫雷游戏的体验和分析, ...
- Bootstrap_Javascript_手风琴
触发手风琴可以通过自定义的 data-toggle 属性来触发.其中data-toggle值设置为 collapse,data-target="#折叠区标识符". 第一步,设计一个 ...
- uboot总结:uboot配置和启动过程2(mkconfig分析)
说明:文件位置:在uboot的目录下,文件名为:mkconfig.本身是一个脚本文件. 它的主要作用的是: (1)创建一个重要的符号链接 (2)创建一个config.mk文件(在include目录下) ...
- Redmine配置
官网步骤说明 http://www.redmine.org/projects/redmine/wiki/RedmineInstall 搭环境 1.MySql 2.RailsInstaller:Redm ...
- ios新特征 ARC详解
IOS ARC 分类: IOS ARC2013-01-17 09:16 2069人阅读 评论(0) 收藏 举报 目录(?)[+] 关闭工程的ARC(Automatic Reference Co ...
- PHP框架、库和软件资源大全(整理篇)
php的资料 https://github.com/ziadoz/awesome-php Awesome PHP A curated list of amazingly awesome PHP lib ...
- Yeoman:适合现代Web应用的现代工作流
Yeoman:适合现代Web应用的现代工作流 Yeoman是Google的团队和外部贡献者团队合作开发的,他的目标是通过Grunt(一个用于开发任务自动化的命令行工具)和Bower(一个HTML. ...
- linux系统下root用户和普通用户的时区不一致
1. 发现这个问题是在root下执行 date -R 和 普通用户下执行 date -R,发现时区不一致 2. 在一些linux机器下,发现是一致的 3. 什么原因呢?找了半天,最后发现 时区一致的机 ...