首页 > 代码库 > hibernate总结
hibernate总结
一、简介:
1) Hibernate是ORM框架之一,该框架包括JDO,TOPLINK,JPA等,hibernate先于JPA出现,hibernate的开发者参与JPA的开发,其中JPA标准大有一统天下的趋势。
2) Hibernate是面向对象的,JDBC是面向过程的。
3) Hibernate封装了sql语句,用户只需定义实体类、建立数据库,并配置数据库连接(hibernate.cfg.xml),说明实体类与数据库之间的映射关系(hbm.xml文件或annotation)就可完成对象的操作。
4) hibernate的映射两种方式:xml方式,annotation注解方式(着重掌握)。MyEclipse可以根据反向生成类,注解也可正向生成数据库。理论上面向对象应该先类后表,但实际工作中,先见表后建类,因为有些db优化操作注解方式无法生成。
5) Hibernate使用的日志接口是slf4j,可实现多种日志,hibernate的日志slf4j-nodep不常用,可以转换为log4j日志。需要导入:
slf4j-api.jar和slf4j-log4j12.jar.
二、Hibernate.cfg.xml的配置:
1) <property name="current_session_context_class">thread</property>
a. 使用getCurrentSession方法时需要设置。
b. 取值:
① thread:上下文:从当前线程中找。
② jta(java transaction api):处理分布式事务
事务分类:connection事务,jta事务。
Connection事务使用一个connection处理。
jta事务需要多个connection处理,需要事务管理器TransactionManager实现)。如产品订单,一个数据库处理产品信息,另一个数据库处理支付信息。运行时需要applicationServer的提供TransactionManager,tomcat不具备TransactionManager。Jboss,WebLogic具备。
2) <property name="hbm2ddl.auto">create</property>
① Create:每次自动创建表
② Update:字段更新时自动创建DDL,更新表。
三、基础配置——主要写在get方法上。
@Entity:注解实体
@Table(name="_animal"):修改表名
@Transient //不往数据库中存,瞬态transient的数据。
@Temporal(TemporalType.DATE):修改Date格式
@Id:注解主键
@Column(name="_name"):修改字段名
@Basic //默认为@Basic
四、主键生成策略
1) xml:generator=”native”
① native:自适应DB
② identity:MySQL,SQLServer自增
③ sequence:Oracle自增
④ uuid:唯一
⑤ asssigned:指定
2) annotation:
① AUTO:相当于xml中native
② IDENTITY:同xml
③ SEQUENCE:同xml
④ TABLE:知道即可
3) 联合主键:主键类需要实现serializable接口。
① 常用方式1:嵌入主键类并在get上@EmbeddedId
② 常用方式2:实体类上@IdClass(PersonPK.class),主键get方法上@Id
五、Hibernate核心开发接口:
1) Configuration(xml方式) & AnnotaionConfiguration(注解方式)
① 管理配置信息:默认名hibernate.cfg.xml
② 用于产生SessionFactory
③ 可以在configure方法中指定hibernate配置文件名称
④ 只需关注一个方法: Configuration().configure().buildSessionFactory();
2) SessionFactory:
① 用来获取和管理Session
② 每个应用通常只需一个,除非要访问多个数据库。
③ 关注两种方法:
a. getCurrentSession():首先查找上下文中的Session,没有则创建新的Session,commit后session自动关闭。可以实现事务(同时成功或同时失败,必须使用同个Session)提交。
b. openSession():总是创建新的session,需要关闭,不建议使用。
六、对象的三种状态:
1) Transient:瞬态,内存中有,Session缓存中没有,数据库中没有,没有ID
2) Persistent:持久态,内存中有,将对象加载到Session缓存中,数据库有,有ID
3) Detached:托管状态(Session关闭,缓存也没了):内存中有,Session缓存中没,数据库中有,有ID
七、Session的方法:
1) clear():清空Session缓存
2) save();
3) delete();
4) flush():刷新Session缓存
5) get(Student.Class,1):立即加载Student对象执行SQL语句,对象成为persistent态,加载到Session缓存中
6) load(Student.Class,1):延迟,生成的是代理对象,用到时才会执行SQL语句并加载到缓存
7) update:更新对象所有字段,若只想更新部分字段,使用HQL:
8) Query query = session.createQuery("update Student s set s.name=‘s‘ where s.id=1");
query.executeUpdate(query);
八、hibernate关系映射(重点)
1) 关系——指的是对象数量之间的关系:一对一,一对多,多对一,多对多。
2) 数据库表与表之间的关系:只有主外键关系。数据库设计时一般遵循主键关联和单向外键关联,比较清晰。
① 单向OneToOne:
数据库设计时,如果两个实体A,B是一对一关系,可以在A中增加B对象的一个引用。并在get方法上写OneToOne。生成表时就把B表的ID作为A表的一个外键。get上写@JoinColumn(name=””)可修改生成的外键的字段名。
② 双向OneToOne:
在B中增加A对象即可,get方法上写@OneToOne @mappedBy(“”)””中为A中getXXX()方法中的xXX。
组件映射:
@Embedded 相当于组件加到了被嵌入对象中。故不需要ID,不需要@Entity不需要在cfg中引入。
③ 单向ManyToOne:(在多的一方增加少的一方的外键,在多的一方增加少的一方的对象引用)
一般为多的一方增加外键。则多的一方增加另一方的对象引用。get上@ManyToOne即可
@JoinColumn(name=””)指定少的一方外键字段名
④ 单向OneToMany:(在多的一方增加少的一方的外键,在少的一方增加多的set类型的对象引用)
在少的一方增加set类型的另一方类型的引用,get上@OneToMany,则默认用ManyToMany的方式,在数据库中生成一张拥有双方ID的临时表。在get上写@JoinColumn(name=””),名称为少的一方的外键字段名,则生成的数据库结果跟ManyToOne一样。
⑤ 双向OneToMany即ManyToOne:
双向就用mappedBy=”主导的对象名”,@OneToMany @ManyToOne
生成的数据库跟一个单向的一样。
⑥ 单向ManyToMany:单向设置在其中一个实体类中引入并@ManyToMany即可
⑦ 双向ManyToMany:双向两边都加入实体类并@ManyToMany,mappedBy设置主导一方。
九、性能优化
1) 级联(CASCADE):在增加、删除等操作时,一并改变和该实体类有关联的实体。只是操作时比较方便,并不是必要的。
操作:
① 1.在映射关系名后@ManyToMany(cascade={CascadeType.ALL}),设置对象之间的关系。
② 2.如设置Dream和Person之间的关系:dream.setPerson(person);单向设一个,双向设两个cascade关联。
a. ALL,任何时候都级联。
b. PERSIST,添加时级联。
c. REMOVE删除时级联。
级联后,保存、删除一个表中的数据时会自动操作级联的表中的数据。
2) 延迟加载/立即加载(fetch)
级联只影响增加删除修改,而fetch影响查询。
① EAGER:查询时关联的表立即加载。
② LAZY:查询时关联的表不加载。
操作:
@ManyToOne(fetch=FetchType.Lazy)即可,则在查询或get,load时改变加载方式。
3) 缓存
① 一级缓存:Session中的缓存
② 二级缓存:SessionFactory中的缓存,当Session中找不到的时候就去二级缓存中找。load,iterator,list查询 默认使用二级缓存。
③ 查询缓存:查询重复sql语句先在查询缓存中找。
适合放在二级缓存中的数据:
a. 经常被访问,
b. 改动不大,
c. 数量有限。
例如:组织机构,帖子类型,用户权限。
4) 事务并发处理:
a. 事务:ACID,原子性,一致性,独立型,持久性。
① 脏读:读了另外一个数据没有提交的数据。
② 不可重复读:同一个数据前后读两次值不同,做了更新。
③ 幻读:读数据的过程中另外的事务向其中插入/删除一条数据,影响了查询结果。
b. 事务隔离机制:取值1,2,4,8。(0001,0010,0100,1000算法效率高,拥有几种权限如CRUD,可以合并为0110)。一般情况下不处理幻读,考虑到效率一般设置为2即read-commited级别。所以要解决不可重复读的问题。
隔离机制 | 取值 | 是否会脏读 | 是否会不可重复读 | 是否会幻读 |
read-uncommited | 1 | √ | √ | √ |
read-commited | 2 | × | √ | √ |
repeatable read | 4 | × | × | √ |
serialzable | 8 | × | × | × |
c. 解决不可重复读的问题:
乐观锁:使用数据库的锁
悲观锁:使用@version
hibernate总结