zoukankan      html  css  js  c++  java
  • 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的那些即可。

      

      

      Confirm之后,accept,安装即可。

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

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

      2.创建持久化类

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

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

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

      6.编写DAO层。

      7.编写Service层。

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

      先上一张完整的目录:

      

      1.创建项目

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

      

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

    单击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。

    生成之后的内容:

    <?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,如下图所示。

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

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

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

    这时候会生成一个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菜单。再查看数据库中就会发现多了一条记录。

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

    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原理。

  • 相关阅读:
    【Codeforces 475F】—Meta-universe(Set)
    【Codeforces 475F】—Meta-universe(Set)
    【UOJ #79】—一般图最大匹配(带花树)
    【UOJ #79】—一般图最大匹配(带花树)
    【NOIp2019模拟】题解
    【NOIp2019模拟】题解
    涉及到的业务逻辑总结
    2016-9-14
    Spring MVC
    2016-9-12
  • 原文地址:https://www.cnblogs.com/GoForMyDream/p/8580183.html
Copyright © 2011-2022 走看看