1.什么是框架,框架从何而来,为什么使用框架?
1.1.框架(framework):
- 1.是一系列jar包,其本质是对JDK功能的拓展.
- 2.框架是一组程序的集合,包含了一系列的最佳实践,作用是解决某一个领域的问题.
最佳实践(Best Practice):
实际上是无数程序员经历过无数次尝试之后,总结出来的处理特定问题的特定方法.
如果把程序员的自由发挥看作是一条通往成功的途径,最佳实践就是其中的最短路径,能极大的解放生产力.
1.2.Web开发中的最佳实践:
分层开发模式(技术层面的"分而治之")
JavaEE开发根据职责的纵向划分:表现层,业务层,持久层:
名称 | 领域 | 职责 | 框架 |
---|---|---|---|
表现层(Predentation Layer) | web/mvc | 负责处理与界面交互的相关操作 | Struts2/Spring MVC |
业务层(Business Layer) | service | 负责复杂的业务逻辑计算和判断 | Spring |
持久层(Persistent Layer) | dao | 负责将业务逻辑数据进行持久化存储 | Hibernate/MyBatis |
1.3.持久层
持久层封装了数据访问的细节,为业务逻辑层提供了面向对象的API,完善的持久层应该达到:
- 1.代码重用性高,可以完成所有的数据访问操作.
- 2.可以支持多种数据库,可以在多种数据库之前任意切换.
- 3.具有相对独立性,当持久层变化时,不会影响上一层(service)实现.
Hibernate.
2.对象关系映射
2.1.定义
对象关系映射(Object Relational Mapping,简称ORM):
是一种为了解决面向对象与关系数据库存在的互不匹配的现象的规范。
简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中。
2.2.目的
- 避免直接使用SQL语句对关系型数据库中的数据进行操作.
- 减少代码编写量,提高产品质量.
ORM 主要解决对象-关系的映射:面向对象概念 面向关系概念
类 | 表 |
---|---|
对象 | 表的行(记录) |
属性 | 表的列(字段) |
2.3.ORM的实现思想:
将关系数据库中表中的记录映射成为对象,以对象的形式展现,程序员可以把对数据库的操作转化为对对象的操作。因此ORM的目的是为了方便开发人员以面向对象的思想来实现对数据库的操作。
ORM 采用元数据来描述对象-关系映射细节:
元数据通常采用 XML 格式,并且存放在专门的对象-关系映射文件中。
2.4.目前流行的ORM框架:SSH
1.JPA:本身是一种ORM规范,不是ORM框架.由各大ORM框架提供实现.
2.Hibernate:目前最流行的ORM框架.设计灵巧,性能优秀,文档丰富.
3.MyBatis:本是apache的一个开源项目iBatis,提供的持久层框架包括SQL Maps和DAO,允许开发人员直接编写SQL.
等
3.Hibernate简介
3.1.什么是Hibernate:
优秀的开源的Java对象持久层轻量级封装框架,既可以在Java应用程序中取代大部分JDBC代码,也可以整合到J2EE系统中作为持久层的解决方案。
Hibernate本身是基于JDBC,对JDBC访问数据库做了抽象和封装.
需要数据库的驱动包.
3.2.Hibernate的优缺点:
- 1):优秀的ORM思想实现,在很大程度的简化了持久层的重复编码工作,有丰富的文档.
- 2):使用java的反射机制,而不是字节码增强程序类实现透明性.
- 3):性能非常优异,支持多种关系型数据库,灵活而简单的实现了复杂的对象关系映射.
- 4):本身性能并不是很好,存在很多优化手段 (一级缓存、二级缓存、查询缓存、抓取策略等)
3.3.Hibernate框架包的结构分析:
下载地址:http://hibernate.org/orm/
Hibernate目录结构:
documentation :开发文档和API.
lib:核心jar包和依赖/相关的jar包.
project:hibernate源码以及配置文件等.
4.Hibernate的CRUD
4.1.准备操作:
- 1:t_user数据库表和模型对象User.
CREATE TABLE `t_user` (
`uid` bigint(20) PRIMARY KEY AUTO_INCREMENT,
`uname` varchar(20),
`usalary` decimal(8,2),
`uhiredate` date
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- 2:User的DAO和DAO测试类.
DAO接口:IUserDAO
DAO实现类:UserDAOImpl
DAO测试类:UserDAOTest
-
3:开发Hibernate应用依赖jar包:
1).MySQL驱动包:mysql-connector-java-5.1.22.jar
2).核心包:Hibnernate根/lib/required/*.jar:
3).日志包:log4j-1.2.14.jar(可以不要)
- 4.Hibernate的配置文件:
*.hbm.xml:映射文件(映射对象和表中的关系)
Hibernate.cfg.xml:Hibernate的主配置文件(包含了和数据库连接相关信息)
User.hbm.xml文件: 针对于哪一个XX类型对象的映射文件就叫做XX.hbm.xml.
映射文件(User.hbm.xml): 关联约束文件hibernate-mapping-3.0.dtd.
Hibernate主配置文件(hibernate.cfg.xml):关联约束文件hibernate-configuration-3.0.dtd.
阅读hibernate.properties文件,找到连接数据库的基本要素.
在hibernate-release-4.3.5.Final\project\etc目录中:
4.2.使用Hibernate实现CRUD操作
DQL操作步骤:
查询操作模板:
1.创建配置对象
2.读取配置文件
3.创建SessionFactory
Hibernate中的Session和HttpSession没有任何关系.
可以简单理解为Connection对象,包含了很多CRUD操作方法.
SessionFactory:创建Session对象的,.好比是DataSource.4.获取Session
5.具体的查询操作
6.关闭Session
-
7.关闭SessionFactory
DML操作步骤:
- 1.创建配置对象
- 2.读取配置文件
- 3.创建SessionFactory
- 4.获取Session
- 5.打开事务
- 6.DML操作
- 7.提交/回滚事务
- 8.关闭Session
- 9.关闭SessionFactory
save和get方法执行流程:
5.常见错误操作
- 1).操作数据库,必须拷贝数据库对于的驱动包.
- 2).hibernate.cfg.xml中的
配置不能出现空格,如:
root
- 3).忘记调用configure()方法,正确写法:
Configuration cfg = new Configuration().configure(); //加载hibernate.cfg.xml文件.
- 4).org.hibernate.PropertyNotFoundException:
找不到对象中指定的属性名.(属性property有getter/setter决定,而不是字段Field决定) - 5).SessionException : Session is closed:不能再关闭Session之后,使用Session对象.
- 6).实体类存在无参数构造器.
- 7).Hibernate并不要求持久化类必须实现java.io.Serializable接口,但对于RMI或JavaEE分布式结构的Java应用,必须实现该接口.Hibernate要求持久化类,必须提供一个不带参数的构造器.
6.Hibernate的API介绍
6.1.Configuration对象:
hibernate的配置对象,主要用于解析Hibernate配置文件和持久化映射文件中的信息,最重要的功能,是用来创建
6.2.SessionFactory对象.(配置文件都要存放在CLASSPATH根路径)
Hibernate3.x中:
可以把所有的配置信息全部放在hibernate.cfg.xml中,一般不使用hibernate.properties.
SessionFactory sf=cfg.buildSessionFactory();
Hibernate4.x中:(了解)
建议把基本配置信息全部放在hibernate.properties中,而在hibernate.cfg.xml只存在引入映射文件的配置:
ServiceRegistry registry = new ServiceRegistryBuilder().buildServiceRegistry();//ServiceRegistry 是 Service 的注册表, 它为Service提供了一个统一的加载/初始化/存放/获取机制.
//Hibernate4.2方式
ServiceRegistry registry = new ServiceRegistryBuilder().build();
//Hibernate4.3方式
ServiceRegistry registry = new StandardServiceRegistryBuilder().build();
SessionFactory sessionFactory = cfg.buildSessionFactory(registry);
还有一些其他的方法:
addClass/addProperties/setProperty/setProperties
在hibernate中,可以直接使用代码完成所有的配置,不一定必须要hibernate.cfg.xml文件(Spring集成Hibernate采用该方式)
SessionFactory对象:
- 1.负责创建Session对象.
- 2.数据库的连接信息是配置SessionFactory;
- 3.SessionFactory是线程安全的,SessionFactory的创建需要很大的系统开销,实际上,在创建sessionFactory的时候才会去连接数据库,一般的,针对一个应用,一个数据库服务器,只需要一个SessionFactory实例就够了.
Connection对象是线程不安全的,DataSource却是线程安全的.
Connection对象每次都要创建新的对象,DataSource在开发中只需要存在一个实例即可. - 4.SessionFactory的重要方法:使用银行转账案例,说明openSession和getCurrentSession
-
5.抽取Hibernate工具类:HibernateUtil
SessionFactory的重要方法:
使用银行转账案例,说明openSession和getCurrentSession
-
1).openSession:这个方法代表,开启一个全新的Session(测试环境)
1.全新的连接,好比创建新的Connection对象.
2.全新的事务
3.全新的一级缓存 -
2).getCurrentSession:得到当前上下文中的session,绑定到当前线程.(开发环境)
1.如果当前上下文中存在session,则使用该session;
2.如果当前上下文中不存在session,则使用opensession创建一个新的session;
3.要使用getCurrentSessoin,必须在hibernate.cfg.xml中配置
thread
4.getCurrentSession得到的session是和事务绑定的(Spring集成Hibernate的方式);
1),无论是DML还是DQL ,都必须开启事务
2),当事务提交的时候,session就跟着关闭了.-->此时不需要人为的调用:session.close() -
3).我们平时在测试的时候,还是使用openSession就可以了,关于事务的解决到spring讲;
6.3.Session对象
通过SessionFactory对象创建而来,包含了Connection对象,封装了很多操作方法.
- 1.save/update/delete/get/createQuery/beginTransaction.
- 2.session不是线程安全的(使用局部变量),所以,session的最大生命周期:一个线程,在web应用当中,一个
session的最大生命周期:request. - 3.Session中有一个缓存,称为一级缓存。存放当前工作单元加载的对象.
在一个session的生命周期之内,连续拿相同类型,相同ID的对象,只需要发送一次SQL. - 4.一级缓存能提高一定的性能,但是有限.
- 5.session加载出来的对象,都存放于一级缓存中进行管理.
- 6.控制一级缓存的方法:
clear():清空一级缓存所有对象
evict(Object o):从一级缓存中清除指定的对象.
6.4.Transaction对象:代表对事务的封装;
- 1.Transaction tx = session.beginTransaction():设置当前事务为活动状态
- 2.Transaction tx = session.getTransaction():得到当前session上面已经活动的事务对象,注意,在调用这个方法之前必须调用beginTransaction()方法;(该方法得到的对象永远不会为空)
常用方法:
1.tx.commit():提交相关联的session实例
2.tx.rollback():撤销事务操作
标准的处理有事务的模板代码:
7.常用的配置和映射细节详解
Hibernate主配置文件(hibernate.cfg.xml):
关联约束文件hibernate-configuration-3.0.dtd.
7.1.连接数据库
阅读hibernate.properties文件,找到连接数据库的基本要素.
在hibernate-release-4.3.5.Final\project\etc目录中:
- 我们不会直接在Hibernate中配置连接池(略-交给Spring).
- 是否显示操作的SQL语句:
hibernate.show_sql=true
- 是否格式化显示操作的SQL语句:
hibernate.format_sql=true
7.2.自动生成数据库表:
根据对象和映射文件,在创建SessionFactory的时候,可以生成对应的数据表:
hibernate.hbm2ddl.auto=create-drop:删除并创建表,关闭SessionFactory时,删除数据库表.
hibernate.hbm2ddl.auto=create:删除并创建表 平时上课,测试
hibernate.hbm2ddl.auto=update:更新表结构:开发项目过程中:
hibernate.hbm2ddl.auto=validate:验证表结构:如果表结构和映射文件不匹配,hibernate启动失败
create-drop和create对比
序列 | 操作 | create-drop | create |
---|---|---|---|
1 | 删除那些表?创建那些表 | 删除本次hibernate管理的对象对应的表;创建hibernate本次管理的对象对应的表; | 删除本次hibernate管理的对象对应的表;创建hibernate本次管理的对象对应的表; |
2 | 如果新加一个domain会怎么处理 | 创建对应的表; | 创建对应的表; |
3 | 如果删除一个domain会怎么处理 | 不管 | 不管 |
4 | 删除 | 一定要正常关闭SessionFactory,才会正常删除表; | 每次都是删除表并重新创建表 |
5 | 使用 | 一般不会使用create-drop | 一般在做测试的时候使用create方法,因为每次都是删除表并重新创建表;所以可以保证多次测试的代码不用重写;注意在黑盒测试的时候不能使用create; |
1).create-drop
- 1.删除那些表?创建那些表:删除本次hibernate管理的对象对应的表;创建hibernate本次管理的对象对应的表;
- 2.如果新加一个domain会怎么处理:创建对应的表;
- 3.如果删除一个domain会怎么处理:不管;
- 4.一定要正常关闭SessionFactory,才会正常删除表;
- 5.使用:一般不会使用create-drop;
2).create
- 1.删除那些表?创建那些表:删除本次hibernate管理的对象对应的表;创建hibernate本次管理的对象对应的表;
- 2.如果新加一个domain会怎么处理:创建对应的表;
- 3.如果删除一个domain会怎么处理:不管;
- 4.使用:
1一般在做测试的时候使用create方法;
2,因为每次都是删除表并重新创建表;所以可以保证多次测试的代码不用重写;
3,注意在黑盒测试的时候不能使用create;
3).update
- 1.检查并修改那些表?修改本次hibernate管理的表;
- 2,如果表已经存在,怎么处理?检查表结构和当前对象结构是否匹配,如果不匹配,尝试更新当前表结构;
- 3,如果表不存在,怎么处理:创建新表;
- 4,如果对象的结构有变化,怎么更新
1.添加一个属性:在表中添加一列;
2.删除一个属性:不管;
3.修改一个属性:尝试修改属性对应的列类型,如果不能修改,抛出警告;
- 5.使用:
1.在黑盒测试的时候使用update;
2.在生产环境不建议使用update(运营过程中);
3.在启动的时候一定要关注由update导致的更新表结构失败;
4).validate
- 1.检查当前hibernate管理的对象对应的表和数据库的表结构是否匹配,如果有任何不匹配,直接报错,hibernate启动失败;
- 2.在生产环境中一般使用vaildate,保证当前数据库表版本和hibernate当前对象版本匹配;
8.单对象映射细节单对象映射细节
持久化对象的要求:
*.hbm.xml文件常见映射细节:
- 1.package是可以不写的,如果不写package,其中所有的类都必须有全限定名.
- 2.在一个hbm.xml中,可以写多个对象的映射,但是一般来说,一个映射文件对应一个对象.建议和类名相同(User.java --> User.hbm.xml)
- 3.class元素的table属性是可以省略的,如果不写table,对应table的名称和类的名称一模一样(大小写一样).
- 4.property元素对应的是对象的属性:fullName
什么是属性:由一对符合命名规范的getter和setter构成的;hibernate找的是getter和setter
hibernate什么时候使用getter:把对象-->数据库列中,getter方法返回的内容就是要保存到数据库中的内容
hibernate什么时候使用setter:数据库列-->对象中,setter方法传入的值就是数据库中的值
hibernate不关心getter和setter方法的可见性
- 5.可以通过修改property元素的access属性来改变访问策略(访问属性/字段).
:使用字段来关联表字段
- 6.property元素的type属性可以为对象的属性添加指定的映射类型
type里面写的类型,不是数据库的类型,是hibernate定义的一种中间类型,
JAVA类型-中间类型-数据表类型
- 7.为列添加更多的额外控制
在property元素的子元素column中,可以添加更多的列的控制条件
- 8.控制属性的可变性:
insert属性决定该列是否出现在INSERT语句中:
:
有值就出现在SQL语句,没有值就不出现:
- 9.auto-import:自动导入,hibernate为其中的对象自动的起一个别名(默认就是类的名称,用于查询)