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

