初识Hibernate

1.问题

这两天弄一个项目,连接了mysql。第一天访问数据库没问题,第二天就报错,异常如下:

Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

这里只摘取一段,很是头疼。去网上查,大多是说mysql的wait_timeout缺省为8小时,mysql数据库中是28800s。如果在wait_timeout秒期间内,数据库连接一直处于等待状态,那么mysql就将该连接关闭,这时你的java应用的连接池仍然合法的持有该连接的引用。所以你第二天操作数据时,会报错。

2.解决

一开始按照网上的思路是更改mysql数据库的wait_timeout字段,最大值是24天/365天(windows/linux)。或者改mysql的配置文件——my.ini/my.cnf(windows/linux)。可是后来想了想,这样过一段时间又会报错,该怎么解决呢。于是后决定试试看hibernate,看看通过这个框架还会导致问题出现吗

3.Hibernate配置

首先引入jar:image

少一个基本会出现各种各样的问题,mysql-connector千万记得。

接着在src目录下写配置文件:hibernate.cfg.xml

image

这里要注意url里面的值,useUnicode=true&

它与jdbc的写法不同,他需要用& 代替;  不然会报错。

接着我们建个包,在这个包里面写个pojo对应数据库字段。同时还要写个对应pojo的映射xml:

image

user类没什么好说的,跟自己数据库字段对应即可

这个xml具体配置如下:

image

class标签下面name对应的是pojo,table是表名。

id是映射的唯一标识,也就是表中的主键。要注意的是<generator>标签里的class属性。我这里写的assigned,意思是用户自定义id,即给定一个id

还有其他6个属性,感兴趣的可以百度,这里就不做介绍了。

4.写一个Util类获取Session

package com.hibernate.DBUtil;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    private static SessionFactory sessionFactory = null; // SessionFactory对象

    static {
        try {
            Configuration cfg = new Configuration().configure(); // 加载Hibernate配置文件
              sessionFactory = cfg.buildSessionFactory();
        } catch (Exception e) {
            System.err.println("创建会话工厂失败");
            e.printStackTrace();
        }
    }

    // 获取Session
    public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        if (session == null || !session.isOpen()) {
            if (sessionFactory == null) {
                rebuildSessionFactory();
            }
            session = (sessionFactory != null) ? sessionFactory.openSession() : null;
            threadLocal.set(session);
        }
        return session;
    }

    /**
     * 重建会话工厂
     */
    public static void rebuildSessionFactory() {
        try {
            Configuration cfg = new Configuration().configure(); // 加载Hibernate配置文件
              sessionFactory = cfg.buildSessionFactory();
        } catch (Exception e) {
            System.err.println("创建会话工厂失败");
            e.printStackTrace();
        }
    }

    // 获取SessionFactory对象
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    // 关闭Session
    public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);
        if (session != null) {
            session.close(); // 关闭Session
        }
    }
}

这里有必要说一下ThreadLocal。因为session是线程不安全的,为了解决并发的问题,防止数据污染,我们在创建session时把她放进ThreadLocal里,这是一个新思路。并不像之前的加synchronized,要程序员自己在各个不同的地方加,这样会显的很烦乱。具体ThreadLocal介绍这里贴一个博客,个人觉得理解的很到位:http://blog.csdn.net/lufeng20/article/details/24314381  ThreadLocal源码内的情况也确实如他所说。

5.CRUD

上面配置好了hibernate,下面来写一些方法来操作数据库

具体方法如下:

package com.hibernate.DBUtil;

import org.hibernate.Session;

import com.hibernate.Entity.User;

public class HibernateORM {
    private HibernateUtil hibernateinit = null;
    private Session session = null;

    public void insert(Object obj) {
        // Hibernate的持久化操作
        try {
            session = hibernateinit.getSession(); // 获取session
            session.beginTransaction(); // 开启事务
            session.save(obj); // 执行数据库添加操作
            session.getTransaction().commit();// 事务提交
            System.out.println("数据添加成功");
        } catch (Exception e) {
            session.getTransaction().rollback();
            System.out.println("数据添加失败");
            e.printStackTrace();
        } finally {
            hibernateinit.closeSession();
        }
    }

    //get方法是在不确定数据库是否存在该信息的情况下获取detail
    public void getDetail() {
        try {
            session = hibernateinit.getSession();
            User user = (User) session.get(User.class, new Integer("4"));
            System.out.println("用户ID:" + user.getId() + ",用户姓名:" + user.getName());
            System.out.println("第一次装载对象");
            User user2 = (User) session.get(User.class, new Integer("4"));
            System.out.println("第二次装载对象");
        } catch (Exception e) {
            System.out.println("get()方法对象装载失败!");
            e.printStackTrace();
        } finally {
            hibernateinit.closeSession();
        }
    }
    
    //load方法是在给定ID的情况下获取detail
    public void loadDetail(){
        try {
            session = hibernateinit.getSession();
            User user = new User();
            session.load(user, new Integer("1"));   //装载对象
            System.out.println("用户ID:" + user.getId() + ",用户姓名:" + user.getName());
        } catch (Exception e) {
            System.out.println("load()方法对象装载失败!");
            e.printStackTrace();
        }finally {
            hibernateinit.closeSession();
        }
    }
    
    public void delete(){
        try {
            session = hibernateinit.getSession();
            session.beginTransaction();
            User user = (User)session.get(User.class, new Integer("3"));
            session.delete(user);
            session.flush();
            session.getTransaction().commit();
            System.out.println("对象删除成功!");
        } catch (Exception e) {
            session.getTransaction().rollback();
            System.out.println("对象删除失败!");
            e.printStackTrace();
        }finally {
            hibernateinit.closeSession();
        }
        
    }
    
    public void update(){
        try {
            session = hibernateinit.getSession();
            session.beginTransaction();
            User user = (User) session.get(User.class, new Integer("4"));
            user.setName("233");
            session.flush();
            session.getTransaction().commit();
            System.out.println("对象修改成功");
        } catch (Exception e) {
            session.getTransaction().rollback();
            System.out.println("对象修改失败");
            e.printStackTrace();
        }finally {
            hibernateinit.closeSession();
        }
    }
    
}

简单的写了一下,这里要注意,在增删改这些操作上,要加事务,不然会报一个Transaction的错误。

最后写一个test测试一下:

image

自己试了里面一些方法,发现控制台输出了SQL语句和执行结果:

image

确实和数据库能对应起来,CRUD操作也都没有问题。

6.昨天写好这些东西后,对数据库操作了一番发现没有问题,今天看看会不会出现通过JDBC操作mysql的wait_timeout问题。结果没有出现,这个方法应该可以不通过修改mysql数据库从而解决。下面还要进行长时间观察,看看有没有这个问题,这里先做一个记录。

原文地址:https://www.cnblogs.com/JJDJJ/p/7258574.html