Hibernate——配置并访问数据库

  Hibernate,对于java来说很重要的一个东西,用于持久层。之前看了很多配置的,都不行,自己来写一个配置成功的。

  环境:jdk1.8,eclipse-jee-oxygen,mysql-connector-java-5.1.46,hibernate 5.2.

  首先要确保你的jdk,eclipse和mysql装好。然后下载jar包,mysql和hibernate的jar包。

   然后安装JBoss插件,eclipse中Help-----eclipse market里面输入JBoss并搜索,找到JBoss之后,install,这里只需要对应hibernate的那些即可。

  Hibernate——配置并访问数据库

  Hibernate——配置并访问数据库

  Confirm之后,accept,安装即可。

  先简单叙述一下开发流程,后面有详细地说明每一步在干什么以及为什么要这么做。

  1.准备开发环境,数据库中创建数据库及表。

  2.创建持久化类

  3.设计映射文件,也就是利用hibernate讲POJO映射到数据库。

  4.创建hibernate配置文件Hibernate.cfg.xml。

  5.编写辅助工具HibernateUtil类,用来实现对Hibernate的初始化并提供获得Session的方法,这一步是我们这次需要的,具体要看你的项目是否需要。

  6.编写DAO层。

  7.编写Service层。

  8.编写测试类,并用Junit测试。

  先上一张完整的目录:

  Hibernate——配置并访问数据库

  1.创建项目

创建Dynamic Web Project项目,命名为MyHibernate,在项目上右键,New---Other,在里面找Hibernate,选择Hibernate Configuration File(cfg.xml)。

  Hibernate——配置并访问数据库

点击Next按钮,在弹出的对话框中选择配置文件保存的目录,一般默认在src目录,同时需要输入配置文件的名称,一般默认为hibernate.cfg.xml即可。继续Next,在弹出的对话框中填写数据库方言(Database dialect)、数据库驱动(Driver class)、数据库URL、用户名、密码等。MySQL数据库的配置如下:

Hibernate——配置并访问数据库

单击Finish,配置文件就创建成功了,后面有需要可以继续编辑该文件。

  2.创建数据库及表。

  在MySQL中创建一个名为mysqldb的数据库,在该数据库中创建一张名为USER的表。创建USER表的语句如下:

create table user(
id int(11),
name varchar(20),
password varchar(12),
type varchar(6),
primary key(id));

  3.编写POJO映射类User.java

  

package org.hibernate.entity;  
  
public class User {  
  
    private int id;//持久化类的标识属性,映射到数据表中的主键列  
    private String name;  
    private String password;  
    private String type;  
    public User() {  
        // TODO Auto-generated constructor stub  
    }  
    public int getId() {  
        return id;  
    }  
    public void setId(int id) {  
        this.id = id;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public String getPassword() {  
        return password;  
    }  
    public void setPassword(String password) {  
        this.password = password;  
    }  
    public String getType() {  
        return type;  
    }  
    public void setType(String type) {  
        this.type = type;  
    }  
      
}  

  4.编写映射文件User.hbm.xml

  这一步可以通过设置直接生成。右键org.hibernate.entity包,new----other,找到hibernate,选择生成hbm.xml。这里只选择自己需要的POJO类生成hbm.xml。

Hibernate——配置并访问数据库Hibernate——配置并访问数据库

生成之后的内容:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2018-3-16 9:16:18 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="org.hibernate.entity.User" table="USER">
        <id name="id" type="int">
            <column name="ID" />
            <generator class="assigned" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="password" type="java.lang.String">
            <column name="PASSWORD" />
        </property>
        <property name="type" type="java.lang.String">
            <column name="TYPE" />
        </property>
    </class>
</hibernate-mapping>

5.编写hibernate.cfg.xml文件

  刚才新建了一个xml文件,里面有一些配置,现在需要增加一些内容。更改之后的内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">314159</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mysqldb</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        
        <property name="hibernate.hbm2ddl.auto">update</property>  
        <!-- 在控制台输出运行时生成的SQL语句,方便调试 -->  
        <property name="show_sql">true</property>  
        <!-- 连接池大小 -->  
        <property name="connection.pool_size">1</property>  
        <!-- 列出所有映射文件 -->  
        <mapping resource="org/hibernate/entity/User.hbm.xml" />  
    </session-factory>
</hibernate-configuration>

6.编写辅助工具类HibernateUtil.java

package org.hibernate.entity;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;

public class HibernateUtil {

    private static SessionFactory sessionFactory;
    // 创建线程局部变量threadLocal,用来保存Hibernate的Session
    private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
    // 使用静态代码块初始化Hibernate
    static {
        try {
            // 读取配置文件方式1,hibernate4.3之前
//            Configuration cfg = new Configuration().configure();
//            // 创建服务注册对象
//            StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
//                    .applySettings(cfg.getProperties()).build();
//            // 创建会话工厂对象SessionFactory
//            sessionFactory = cfg.buildSessionFactory(serviceRegistry);
//            
            // 读取配置文件方式2,hibernate4.3之后
            ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().configure("/hibernate.cfg.xml").build();
            //创建会话工厂对象
            sessionFactory = new MetadataSources(serviceRegistry).buildMetadata().buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }

    // 获得SessionFactory的实例
    public static SessionFactory getsSessionFactory() {
        return sessionFactory;
    }

    // 获得ThreadLocal对象管理的Session
    public static Session getsSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        if (session == null || !session.isOpen()) {
            if (sessionFactory == null) {
                rebuildSessionFactory();
            }
            // 通过SessionFactory对象创建Session对象
            session = (sessionFactory != null) ? sessionFactory.openSession() : null;
            // 将Session对象保存到线程局部变量threadLocal中
            threadLocal.set(session);
        }
        return session;
    }

    // 关闭Session实例
    public static void closeSession() {
        // 从线程局部变量threadLocal中获取之前存入的Session实例
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);
        if (session != null) {
            session.close();
        }
    }

    // 重建SessionFactory
    public static void rebuildSessionFactory() {
        Configuration configuration = new Configuration();  
        configuration.configure("/hibernate.cfg.xml");
        StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySettings(configuration.getProperties()).build();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
    }

    // 关闭缓存和连接池
    public static void shutdown() {
        getsSessionFactory().close();
    }
}

这里面有一个地方要注意,就是上面的红色注释,创建SessionFactory的方式因为hibernate版本有点不一样,如果选择了不适合的版本,在后面Junit测试的时候,会报“org.hibernate.MappingException: Unknown entity:XXXXXXXXXXXXXXX"的错。

7.编写DAO层接口UserDAO.java

package org.hibernate.dao;

import java.util.List;

import org.hibernate.entity.User;

public interface UserDAO {

    public void save(User user);

    public User findByIdGet(int id);

    public User findByIdLoad(int id);

    public List<User>  findByHQL(String hql);

    public void delete(User user);

    public void update(User user);
}

8.编写DAO层实现类UserDAOImpl

package org.hibernate.dao;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.entity.HibernateUtil;
import org.hibernate.entity.User;


public class UserDAOImpl implements UserDAO {

    // 添加用户,需要事务管理
    @Override
    public void save(User user) {
        // 创建Session实例
        Session session = HibernateUtil.getsSession();
        // 创建Transaction实例
        Transaction tx = session.beginTransaction();

        try {
            // 使用Session的save方法将持久化对象保存到数据库
            session.save(user);
            // 提交事务
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            // 出现异常,回滚事务
            tx.rollback();
        } finally {
            // 关闭Session连接
            HibernateUtil.closeSession();
        }

    }

    // 根据id查找用户 ,可以不需要事务管理 Get方式
    @Override
    public User findByIdGet(int id) {
        User user = null;
        Session session = HibernateUtil.getsSession();
        // 使用session的get方法获取指定id的用户
        user = (User) session.get(User.class, id);
        if (user == null || "".equals(user)) {
            System.out.println("查询id为:" + id + "无结果....");
        }
        session.close();
        return user;
    }

    // 根据id查找用户 ,可以不需要事务管理 Load方式
    @Override
    public User findByIdLoad(int id) {
        User user = null;
        Session session = HibernateUtil.getsSession();
        // 使用session的方法获取指定id的用户
        user = (User) session.load(User.class, id);
        if (user == null || "".equals(user)) {
            System.out.println("查询id为:" + id + "无结果....");
        }
        session.close();
        return user;
    }

    // 根据HQl语句查询
    @Override
    public List<User> findByHQL(String hql) {
        List<User> list = new ArrayList<>();
        Session session = HibernateUtil.getsSession();
        list = session.createQuery(hql).list();
        session.close();
        return list;
    }

    // 删除用户 ,需要事务管理
    @Override
    public void delete(User user) {
        Session session = HibernateUtil.getsSession();
        Transaction tx = session.beginTransaction();
        try {
            session.delete(user);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        } finally {
            HibernateUtil.closeSession();
        }
    }

    // 修改用户
    @Override
    public void update(User user) {
        Session session = HibernateUtil.getsSession();
        Transaction tx = session.beginTransaction();
        try {
            session.update(user);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
            tx.rollback();
        } finally {
            HibernateUtil.closeSession();
        }
    }
}

 到这里整个Hibernate项目就完成了,下面需要的是测试。

9.编写测试类UserTest.java

这里用Junit测试,如果没有导入Junit的要先导入。在HibernateDemo项目名称上右击,选择Properties,在弹出的窗口左侧选择Java Build Path选项,然后在右侧界面中选择Libraries标签,点击Add Library按钮,在弹出的窗口中选择Junit,如下图所示。

Hibernate——配置并访问数据库

然后点击Next,在version一栏选择Junit 4,然后点击Finish。这样Junit包就引入到项目中了。

接下来在项目中新建org.hibernate.test包,在包名上右击,依次选择New->Junit Test Case菜单,在弹出的窗口中填写测试类的名称和需要测试的类的名称(这个需要填写完整包名),如下图所示:

Hibernate——配置并访问数据库

点击Next按钮,可以选择需要测试的方法,根据需要选择即可。

Hibernate——配置并访问数据库

这时候会生成一个UserTest类,里面包含的是一些空方法,我们要测哪些就给哪些加上方法体。

例如重写testSave,下面是重写之后的类:

package org.hibernate.test;

import static org.junit.Assert.*;

import org.hibernate.dao.UserDAO;
import org.hibernate.dao.UserDAOImpl;
import org.hibernate.entity.User;
import org.junit.Test;

public class UserTest {

    @Test
    public void testSave() {
        UserDAO userDAO=new UserDAOImpl();  
        try{  
            User u=new User();  
            // 设置User对象的各个属性  
            u.setId(20);  
            u.setName("zhangsan");  
            u.setPassword("123456");  
            u.setType("admin");  
            // 使用UserDAOImpl的save方法将User对象存入到数据库  
            userDAO.save(u);  
        }catch(Exception e){  
            e.printStackTrace();  
        } 
    }

    @Test
    public void testFindByIdGet() {
        fail("Not yet implemented");
    }

    @Test
    public void testFindByIdLoad() {
        fail("Not yet implemented");
    }

    @Test
    public void testFindByHQL() {
        fail("Not yet implemented");
    }

    @Test
    public void testDelete() {
        fail("Not yet implemented");
    }

    @Test
    public void testUpdate() {
        fail("Not yet implemented");
    }

}

接下来在UserTest.java文件名称上右击,依次选择Run As ->Junit Test菜单。再查看数据库中就会发现多了一条记录。

Hibernate——配置并访问数据库

这里可能有报错,像上面说的

1.“org.hibernate.MappingException: Unknown entity:XXXXXXXXXXXXXXX”这个是因为SessionFactory获取的方式不对,因为hibernate的版本问题,根据上面对应的红色注释改一下就好了。

2.ERROR: Field 'id' doesn't have a default value。这个是因为字段的问题,自动生成的User.hbm.xml可能不太一样。

<id name="id" type="int">
            <column name="ID" />
            <generator class="assigned" />
        </id>

这里的generator对应的是数据库中的id字段是否自动增长,assigned就是我写进去20就是20,如果有的自动生成了native,表示的是从1开始自增,如果数据库中没有相应的设定的话可能会报错,所以这里注意一下。

参照原文地址:http://blog.csdn.net/fxdaniel/article/details/42420779

到这里整个项目的创建到测试都完成了,现在来说一下我对每个步骤在干什么和为什么要这么做的理解。

1.创建项目。这里由于使用了JBoss,所以简化了很多。hibernate.cfg.xml是hibernate中非常重要的一个xml文件,里面是一些hibernate的配置,其中session-factory最重要。试想一下我们以前用JDBC连接数据库时候的操作,加载驱动、url、用户名、密码等等,这里也是一样,你既然要操作数据库,最根本的就是连接数据库,所以hibernate的根就是在这个xml中,这里面让jvm知道用的驱动、url、用户名、密码、以及数据库方言(也就是数据库种类mysql啊还是oracle还是sqlserver啊)。hibernate简化了jdbc中一系列操作,直接通过xml配置文件来配置这些信息。

2.编写POJO类(持久化类)。首先要明确hibernate是服务于持久层,什么是持久层,持久层就是存储数据的,在一个项目中,数据要持久地保存。操作数据库实际上是在操作我们面向的对象也就是POJO类,比如我们有一堆桌子,面向对象设计这个桌子,桌子的重量啊,形状啊等信息会被看作是桌子的属性,而数据库里存的也是这些东西。

3.生成映射文件User.hbm.xml。数据库和我们的类(也就是POJO类)是对应的,但是即使我们知道对应,jvm不知道啊,怎么让他知道,用mapping来匹配。一个POJO类对应一个table,既然对应了,那POJO里面的属性和table的字段肯定也是要对应的,因为属性和字段表示的都是桌子的实际性质。所以映射文件的配置,就是让jvm知道那个POJO类对应哪个table。所以看看这个xml里面的配置,是不是和数据库中的字段配置很相似。

4.编写hibernate.cfg.xml文件。一开始生成了一个xml文件,但是这个xml只是在有数据库的时候生成的,但是我们要具体操作哪一个表的时候,xml就不知道了。现在我们的目的是添加一个user进入,那也就是说我们要操作user类,user类对应数据库里的user表,但是jvm现在只知道要操作mysql数据库,而上一步里面,我们让jvm知道了user类和user表是对应的,可是user表在哪个数据库里面存着呢?mysql还是oracle?mysql下的db还是oracle下的db?很自然的,现在只需要让jvm把mysql数据库和mapping对应起来,而这个mapping就是user类和user表的映射。现在整个逻辑通了,操作user类---映射到mysql数据库--映射到user表。

5.编写辅助工具类。刚才我们说的那些东西,都是保存在hibernate.cfg.xml下面,而那下面的标签是<session-factory>,这个SessionFactory是很重要也很重的一个东西,既然刚才说的东西都保存在这里面,我们用的时候肯定也都是从这里面取,所以这个辅助工具类的就是为了取处这个SessionFactory。

6.编写DAO层接口。在三层视图层、业务层、持久层的逻辑中,DAO也就是database access object,直接面向数据库。成熟的编程方式是先写接口,再写实现类。所以DAO层接口和实现分开。

7.DAO层实现类。这个就是利用取出的SessionFactory,再取出SessionFactory中我们需要的元素,操作这些元素也就是直接面向了数据库,通过这个实现类来完成我们的目的。

8.一个Junit测试类。没啥说的,测试项目。

希望通过这个配置来理解简单的hibernate原理。

Hibernate——配置并访问数据库Hibernate——配置并访问数据库