事务的特点(ACID)
1)原子性(Atomic)
事务由一个或多个行为绑在一起组成的,好像一个单独的工作单元。事务中的操作要么都发生,要么都不发生。
2)一致性(Consistent)一旦一个事务结束了(不管成功与否),系统所处的状态和它的业务规则是一致的。
3)隔离性(Isolated)事务应该允许多个用户操作同一个数据,一个用户的操作不会和其他用户的操作相混浊。
4)持久性(Durable)一旦事务完成,事务的结果应该持久化。
这个问题在面试中也经常被问到,下面我就来系统的和大家分享一下,面试也就OK了。
下面来看一下懒加载的介绍,如下所示
延迟加载就是懒加载,使用懒加载是解决了负载问题,也就是说懒加载后不会立即去访问数据库,而是尽量延迟,延迟到用户执行数据库查询命令的时候或者使用initialize方法的时候去和数据库交互,这样就减轻了与数据库交互的压力,如果缓存中有数据的话会优先考虑缓存数据,总之是尽量避免和数据库的直接交互,但有些时候也会出现数据没有得到及时更新的错误数据,所以,在金融等方面的项目开发的时候尽量避免懒加载。比如在统计论坛数据访问量等要求不是很严格的情况并且数据量比较大的情况下可以使用懒加载。
【load】load方法会导致懒加载出现,如果要数据及时送入数据库的话,使用save方法时,load会延迟至强制访问数据库执行,比如get方法调用的时候。
【one to one映射】对于懒加载,一对一映射中的constrained属性设置为true的时候实现懒加载,lazy决定了什么时候进行懒加载,而fetch决定了抓取的方式。
【mang to one映射】对于多对一映射中,默认情况下是懒加载的,这样有利于减轻系统负载,如果要取消懒加载进行查询的话,在集合端中把lazy属性设置为false就可以。
【总结】懒加载是通过代理方式实现的,代理的对象在访问的时候才会去和数据库进行交互,前提是session没有被关掉的情况下。
在web开发中,我们也可以使用opensessioninview来解决这样的问题,这就要使用到一个类ThreadLocal,事物都有两面性,使用这种机制也有一些缺点
(1)并发性减弱
(2)内存消耗加大
使用这种模式可以解决以下问题:
(1)hibernate事物边界问题
(2) 因session关闭导致hibernate延迟加载例外的问题
OpenSessionInView模式:
* 需要构建一个过滤器,把事物的创建及提交放在过滤器里进行。
* 加大session的有效范围,把session放在当前线程里(ThreadLocal),使session在当前线程内有效,并且在当前线程内访问的是同一个session。
这个过滤器在spring的开发包里有,也可以自己写
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.yx.zzg.util.HibernateUtil;
public class OpenSessionInView implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filter) throws IOException, ServletException {
Transaction tx = null;
Session session = null;
try {
session = HibernateUtil.getThreadLocalSession();
tx = session.beginTransaction();
filter.doFilter(request, response);
tx.commit();
} catch (Exception e) {
if (tx != null) {
tx.rollback();
throw new RuntimeException(e.getMessage(),e);
}
} finally {
HibernateUtil.colseSession();
}
}
public void init(FilterConfig arg0) throws ServletException {
}
}
下面来写个工具类,来获取session,代码如下所示
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory sessionFactory;
//创建一个ThreadLocal对象
private static ThreadLocal threadSession = new ThreadLocal();
private HibernateUtil() {
}
static {
Configuration cfg = new Configuration().configure();
sessionFactory = cfg.buildSessionFactory();
}
/**
* 从当前线程中获取session,如果没有,则得到session,并将此session放入当前线程中
* @return
*/
public static Session getThreadLocalSession() {
Session session = (Session) threadSession.get();
if (session == null) {
session = getSession();
threadSession.set(session);
}
return session;
}
/**
* 关闭session,并将当前线程中的session设置为null
*/
public static void colseSession() {
Session session = (Session) threadSession.get();
if (session != null) {
session.close();
threadSession.set(null);
}
}
public static Session getSession() {
return sessionFactory.openSession();
}
}
这样做就不会有懒加载异常出现了。