hibernate,以及sql执行顺序、数据锁

来源:互联网 发布:淘宝上买彩票 编辑:程序博客网 时间:2024/06/06 05:40
1、hibernate的findbyExample()方法不支持主键查询,意思是就算你设置了主键,在构建原生sql的时候也会把主键忽略掉
确切的说是不支持主键,不支持外键不支持null
2、Hibernate4.1已经可以自动建表,所以开发时只需要自己开发类然后配置好就OK。不需要考虑怎么建表
3、从spring3.1开始, 已经不提供Hibernate4的 HibernateDaoSupport和HibernateTemplate,而是直接使用原生的
Hibernate4 API来获得session.如果管要在spring3中配置sessionFactory,或者管理事务,代码如下:
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate4.HibernateTemplate">
  <property name="sessionFactory" ref="sessionFactory"></property>


</bean>
4、dialect 指明hibernate连接的数据库方言 不同的数据库 方言在hibernate中是不一样的 连接数据库时必须对应的方言
连接对应的数据库


线程安全无非是要控制多个线程对某个资源的有序访问或修改
5、悲观锁即select... for update的锁表的过程,也就是说当本次查询结束并提交了事物,那么针对于此表的更新操作才能继
续进行,否则将使更新操作处于wait状态,而且必须是查询在前更新操作在后时才会起作用


MySQL中select * for update锁表的范围


由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例) ,
否则MySQL将会执行Table


Lock (将整个资料表单给锁住)。 举个例子: 假设有个表单products ,里面有id跟name二个栏位,id是主键。


例1: (明确指定主键,并且有此笔资料,row lock)


SELECT * FROM products WHERE id='3' FOR UPDATE;


SELECT * FROM products WHERE id='3' and type=1 FOR UPDATE;


例2: (明确指定主键,若查无此笔资料,无lock)


SELECT * FROM products WHERE id='-1' FOR UPDATE;


例2: (无主键,table lock)


SELECT * FROM products WHERE name='Mouse' FOR UPDATE;


例3: (主键不明确,table lock)


SELECT * FROM products WHERE id<>'3' FOR UPDATE;


例4: (主键不明确,table lock)


SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;
注1: FOR UPDATE仅适用于InnoDB,且必须在交易区块(BEGIN/COMMIT)中才能生效。


注2: 要测试锁定的状况,可以利用MySQL的Command Mode ,开二个视窗来做测试。
在MySql 5.0中测试确实是这样的


另外:MyAsim 只支持表级锁,InnerDB支持行级锁 添加了(行级锁/表级锁)锁的数据不能被其它事务再锁定,也不被其它事务修改


(修改、删除) 。是表级锁时,不管是否查询到记录,都会锁定表。


#######乐观锁#######
乐观锁
是根据版本控制来实现的,更新的时候通过比对版本号来确定更新是否合法,要大于当前版本号
确切的说是当要更新数据的时候的更新条件hibernate会自动追加一个限制条件就是version= ,如果该数据已经被另一个操作人员
更新了那么数据库当前数据就会大于本操作中的数据,更新就会报错“Row was updated or deleted by another transaction”
异常的名字叫做‘HibernateOptimisticLockingFailureException’,可以放在catch中处理,hql长这样:
update
        a_wdq 
    set
        ACT=?,
        CREATE_BY=?,
        CREATE_DATE=?,
        CREATE_NAME=?,
        NAME=?,
        UPDATE_BY=?,
        UPDATE_DATE=?,
        UPDATE_NAME=?,
        VERSION=? 
    where
        ID=? 
        and VERSION=? 
其中每更新version一次的增加是自动进行的,怎样防止手动改变version?把bean(pojo?)中version的set
方法设置为private
基于配置的bean version应当紧跟ID主键,基于注解的则没有这个限制


mybatis如何实现乐观锁?从乐观锁原理入手加个version字段就行了(我觉得)虽然没有
hibernate显得自动但其实一样


6、hibernate4获取session比较简单首先Autowired  Sessionfactory然后getCurrentSession()就可以获得hibernate的当前会话
不需要opensession
session信息然后createQuery()执行hql,然后会获得query对象,再设置分页信息,最后.list()就可以了,query的setFirstResult()
要从零开始表示第一个
 Query query = session().createQuery(sb.toString());
query.setFirstResult(0);
query.setMaxResults(10);
*hql的执行一定要在service里!不可以是Dao,取决于配置如果报没有权限那么最好在service层里


使用session()获取到currentSession之后呢可以通过get方法来获取实体类,相当于findById,前提是这个类必须已经
实现序列化了


什么是序列化,序列化就是把一个java对象转换为字节序列,然后可以吧这个字节序列写入到一个输出流中,Serializable
标名该对象是可以被序列化的,否则报错
目的呢:一是通过序列化可以实现持久化,而是通过序列化可以对象数据的远程传输


反序列化就是把字节序列还原成java对象
7、一个类里面引用另一个类作为成员变量,一定是joinColumn而不是column,然后还要加上ManytOne的注解,否则left join fetch
会报空指针错误,每个fatch都引用一次
@ManyToOne(fetch = FetchType.LAZY)o
@JoinColumn(name ="ACCOUNT",nullable=true)
8、想要获取刚刚插入的数据的id?直接在保存后调用getId就可以了,此时已经根据指定id策略生成了Id并且插入到了数据库,缓
存里有
所以可以获取到
9、删除实体,用session的delete方法,如果进行批处理的话最好每20次进行一次flush和clear


10、缓存


2级缓存的作用范围是根据id获得对象的查询


二级缓存的工作可以概括为以下几个部分:


在执行各种条件查询时,如果所获得的结果集为实体对象的集合,那么就会把所有的数据对象根据ID放入到二级缓存中。


当Hibernate根据ID访问数据对象的时候,首先会从Session一级缓存中查找,如果查不到并且配置了二级缓存,那么会从二级缓存中查
找,如果还查不到,就会查询数据库,把结果按照ID放入到缓存中。
删除、更新、增加数据的时候,同时更新缓存。


对于放入缓存中的数据不能有第三方的应用数据对数据进行修改(其中也包括自己的程序中的用其他方式进行的数据修改,例如jdbc),
因为那样hibernate将不会知道数据已经被修改也就无法保证数据库与缓存的一致性


只有配置了二级缓存的对象才会被放置在二级缓存中,二级缓存通过<cache>元素来进行配置


11、hibernate.find(),是在缓存中查找,没有找到才去数据库查找,而session.createQuery()则是直接去数据库查找


find方法与saveOrUpdate方法连用可以批量查找更新新增,意思是如果数据库没有就新建,新建后再find同样的记录就会查出
刚刚建立一条新纪录,内存中已经有了(虽然他还没有进入数据库,因为循环完后才commit),而createQuery每次查询结果都相同(查不到,因为数据库
里没有该数据)





















原创粉丝点击