📄 hibernate.txt
字号:
七、如何实现hibernate的annotation
1、annotation将相关的配置写在代码中,而不是写在xml中
这样可以减少xml文件,方便维护。
2、当用到hibernate3.2的注解时,不能用Configuration而是用
AnnotationConfiguration加载相关的配置文件,其可以加载
*.hbm.xml也以加载有注解的类,一个表只能用一种方式加载,
如果用两种就会出错。
3、在hibernate.cfg.xml说明注解类的位置
<mapping class="hibernate.Users"></mapping>
一、为什么用annotation
annotation通过注解可以更方便的进行开发,也是将来spring、hibernate、strust转化的方向。
二、hibernate中annotation的特点
hibernate3.2以上版本支持annotation,其注解与ejb3.0几乎一样,
配置及方法操作与已有的hibernate是一样,只是核心类中的Configuration要改成
AnnotationConfiguration加载核心配置文件hibernate.cfg.xml文件。
hibernate.cfg.xml中可以加载*.hbm.xml也可以加载有注解的类
<mapping resource="hibernate/customer.hbm.xml"/>:加载customer.hbm.xml文件
<mapping class="hibernate/Buy"/>:加载Buy类
三、具体的注解
1、类名类的说明:
@Entity
@Table(name = "users")
1、主键:在get方法之前说明
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
若没有@GeneratedValue注解,主键的值需要开发人员在编程中给定,不能自动生成。
若有@GeneratedValue,主键的值不需要开发人员给定,由数据库自动生成。
2、字段:
1、@Transient //声明其是一个属性,不存于数据库中
2、若没写任何说明,字段名与数据库字段名相同
3、字段具体说明:
@Column(name = "email") //属性名与数据库字段名不同,通过name说明具体字段
@Basic(fetch = FetchType.LAZY) //说明当前字段是延迟加载
4、OneToMany:如果有两个表,一个是one,另一个是many,该注解在one中,mappedBy="role"
"role"与many中Role类型属性要一致,否则报错。
@OneToMany(mappedBy = "role") //
@OrderBy("name")
5、ManyToOne:该注释在many对象中设置,CascadeType.PERSIST代表主增从增,CascadeType.MERGE代表
主改从改。
@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "role_id") //role_id是many表对应的外键列名
hibernate高级应用
事务的四大特点?
原子性:要么全成功,要么全失败
隔离性:事务与事务之间不影响
一致性:代码实现所有业务相关的操作
持久性:保存到数据库中
对于一个表,hibernate对应的主键生成机制有很多种?
assigned:主键值需要手动给定,开发人员必须手动给值
native:主键由数据库自动生成,hibernate不管,开发人员也不用管。
七、如何实现hibernate的annotation
1、annotation将相关的配置写在代码中,而不是写在xml中
这样可以减少xml文件,方便维护。
2、当用到hibernate3.2的注解时,不能用Configuration而是用
AnnotationConfiguration加载相关的配置文件,其可以加载
*.hbm.xml也以加载有注解的类,一个表只能用一种方式加载,
如果用两种就会出错。
3、在hibernate.cfg.xml说明注解类的位置
<mapping class="hibernate.Users"></mapping>
没有锁出现的问题?
1、脏读:后一个事务处理的数据是前一事务修改但没有提交的数据。
事务1:
update buy set amount=amount+100 where buyID=1;
sleep(1000);
rollback;
事务2:数据来源事务1修改的数据
update buy set amount=amount+100 where buyID=1;
commit;
2、覆盖更新:两个事务同时读取数据,
后一处事务将前一个事务修改的数据覆盖了。
事务1:
update buy set amount=amount+100 where buyID=1;
sleep(1000);
commit;
事务2:数据来源事务1修改的数据
update buy set amount=amount+100 where buyID=1;
commit;
3、不可重复读:一个事务两个相同的select语句,第一次读取的数据
与第二次读取的数据不一样,主要针对select语句。
事务1:
select * from buy;
sleep(1000);
select * from buy;
commit;
事务2:数据来源事务1修改的数据
update buy set amount=amount+100 where buyID=1;
commit;
4、幻想读:第一次读有,第二读没有,反之亦然。
与第二次读取的数据不一样,主要针对insert、delete。
事务1:
select * from buy;
sleep(1000);
select * from buy;
commit;
事务2:数据来源事务1修改的数据
delete from buy where buyID=1;
commit;
锁的分类?
1、读未提交
2、读已提交(数据库的默认方式)
1、读取的数据是已提交的,防止脏读。
2、对于更新,在提交之前会将当前行的版本与数据库的版本
比较,若小于数据库的版本报错,回退。若等于数据库的版
本提交。
3、分类:
乐观锁:一个游标取出的行,另一个事务可以更新,
如前游标所在事务更新另一事务已更新的数据时会
与数据库的版本比较,发现版本小于数据库的版本,
报错,回退。
增强了并发性,不能保证当前游标一定修改成功。
悲观锁:一个游标取出行后,对所有的行加锁,其余的事务只可
以查,不可以改。
弱化了并发性,但能保证当前游标一定修改成功。
3、可重复读:将上一个select取出的数据保存一个副本,下一个select语句直接从
副本中取。
4、串行化:一个事务对一个表select后,针对该表其余的事务只能读,不可
增删改。
事务的实现方式?
1、代码式
con.setAutoCommit(false);
con.commit();
Transaction trans=session.beginTransaction();
trans.commit();
trans.rollback();
2、声明式:通过注解或xml文件配置具体的事务处理
1、spring
2、ejb2
3、ejb3
spring/ejb2/ejb3选择事务的方式?
1、required:默认的方式,有则用已有的事务,没有则产生一个新的事务。
2、mandanory:有则用,没有则报错
3、required_new:不管前面有没有都产生一个新的,
如果有将前一个事务挂起用新的事务
如果没有用新的事务。
4、support:有则用,没有则不用。
5、not supported:有则报错,没有正常运行。
hibernate缓存的分类:
1、事务级:就是session级,即一级缓存,缓存的数据在当前事务内有效,
当前事务结束,缓存结束。
2、应用级:就是SessionFactory,即二级缓存,缓存的数据在整个应用程序内
有效,所有事务都可以共享二级缓存。
人为控制SessionFacatory只有一个实例。
3、集群级:有多个应用服务器,每一个应用服务有一个SessionFactory,
服务器与服务器可以通信。
要慎用,因为服务器与服务器通信及交互会占用大量的资源。
缓存的原则:
1、数据的大小在可接收的范围内。
2、重复查询使用率的。
3、更新小或并发更新小。
缓存的实现(ehcache):
1、将ehcache.jar包拷入到lib目录下
2、在src根目录下加入ehcache.xml文件
3、在hibernate.cfg.xml中加入ehcache的驱动属性
及支持查询的缓存
4、在*.hbm.xml文件中加入<cache usage="read-write"/>
5、在执行query之前设置setCacheable(true)
iterator与list方法之间的区别
1、list只执行一次sql,利用缓存的前提是Hql必须相等。
如果hql相等,在缓存中没有会通过主键查找对应的对象。
2、如果没有缓存iterator会执行(n行+1)将sql,第一个sql是查询
出所有的主键,第二种sql是根据主键查找到得每一个对象,有多少
行就要执行对应行数的sql
只要缓存中有iterator就会用。
3、第一次查询用list方法,以后的查询用iterator
六、hibernate中的manyToMany
power:权力
private Set<Role> roles;//及get、set方法
配置文件信息:
<set name="roles" table="powerrole">
<key column="powerID"/>//powerID是中间的外键列
<many-to-many class="hibernate.Role" column="roleID"/>
</set>
select * from role where roleID in
{
select roleID from powerrole where powerID="当前对象的主键";
}
role:角色
private Set<power> powers;//及get、set方法
配置信息
<set name="powers" table="powerrole">
<key column="roleID">
<many-to-many class="hibernate.Power" column="powerID"/>
</set>
powerrole:中间表
get方法与load方法区别
1、相同点
get/load都根据类说明及主键查找
在hibernate3.2都会利用二级缓存
2、不同点
get:
1、返回的是一真实的对象
2、如果没有找到返回null
load:
1、返回的是一个代理
2、如果没有找到返回ObjectNotFoundException
缓存的特点:
1、load、get、update、saveOrUpdate、save、delete都会自动更新缓存
2、query.exeuteUpdate()执行效率但不同步缓存
3、删除缓存中的数据
--一级缓存
session.evict(Customer.class)
--二级缓存
sessionFactory.evict(Customer.class)
4、利用缓存的过程
首先在一级缓存中找,如果没找到在二级缓存中找,
如果还没有找到执行sql数据库中查找。
hibernate的优化策略:
1、选择适当的缓存机制,如那些表需要二级缓存
2、管理好session的生命周期,一般是一个线程一个session
3、使用延迟加载
OneToMany或ManyToOne可以用延迟加载
大文本或大字节也用延迟加载
4、尽量使用乐观锁而不表悲观锁。
非观锁:
1、
Query query1=session.createQuery("select * from Customer for update");
2、
Query query1=session.createQuery("select * from Customer");
query1.setLockMode("Customer",LockMode.UPGRADE);
乐观锁:默认的方式
<class
optimistic-lock="version/none"
/>
5、如果可能主键使用uuid,而不是identity或native
在增加时对于类型是identity主键,会生成两个sql
第一个sql是取最大的主键
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -