主流的數據庫是關係型數據庫,而編程的思想是面向對象的,如何將對象存儲到關係型的數據庫中,消除對象—>關係的阻抗,ORM(Object Relation Model)對象關係模型就出現了,而hibernate就是基於ORM的框架.下面我來聊聊hibernate的手動配置過程.
配置環境:eclipse,mysql數據庫,hibernate的jar包和連接mysql數據庫用的jar包.
配置前提:在mysql數據庫中,名字爲sqdb3的數據庫,有一個叫employee的表.表的字段創建入下:
use spdb3;
create table employee(
id int PRIMARY key auto_increment,
username varchar(64) not null,
email varchar(64) not null,
hiredate date not null
);
employee表裏面的內容自己可以隨意添加.
配置的思想是先建立一個POJO對象,配置Employee.hbm.xml文件,最後配置hibernate.cfg.xml文件.先展示一下各個文件所在的位置.
①先解釋一下POJO的作用,它是一個類(對象類),它所用擁有的屬性對應的是表中的字段,方法是set/get屬性.用來映射employee.Employee.java的代碼如下:
package com.hsp.domain;
import java.util.*;
import java.io.*;
//建議我們的domain對象的名稱就是對應
//表的首字母大寫,domain對象/javaBean/pojo
//該pojo按規範應當序列化,目的是可以唯一的標識該對象,同時可以在網絡和文件上傳輸
public class Employee implements Serializable{
static final long serialVersionUID=1L;
private Integer id;
private String username;
private String email;
private Date hiredate;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getHiredate() {
return hiredate;
}
public void setHiredate(Date hiredate) {
this.hiredate = hiredate;
}
}
②在與POJO同一個目錄下的Employee.hbm.xml文件其實是一個對象關係映射文件.內容如下:
<?xml version="1.0" encoding="utf-8"?>
<!-- 映射文件需要一個dtd -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 該文件用於配置domain對象和表的映射關係 -->
<hibernate-mapping package="com.hsp.domain">
<class name="Employee" lazy="true" table="employee">
<!-- id元素用於指定主鍵屬性 -->
<!-- mysql的數據庫表 id 主鍵對於設置自增長 -->
<id name="id" type="java.lang.Integer">
<column name="id"/>
<generator class="identity"/>
</id>
<!-- 對其他屬性還有配置 -->
<property name="username" type="java.lang.String">
<column name="username" not-null="false" />
</property>
<property name="email" type="java.lang.String">
<column name="email" not-null="false"></column>
</property>
<property name="hiredate" type="java.util.Date">
<column name="hiredate" not-null="false"></column>
</property>
</class>
</hibernate-mapping>
讓我來簡單解釋一下這個Employee.hbm.xml文件的內容,
<hibernate-mapping package="com.hsp.domain">
<class name="Employee" lazy="true" table="employee">
這個是將對象類(Employee)和表(employee)對應起來,其中lazy表示的是懶加載,這個作用之後在解釋.
<id name="id" type="java.lang.Integer">
<column name="id"/>
<generator class="identity"/>
</id>
id這個字段是用來唯一表示表中的主鍵的屬性,name表示的其實就是Employee.java中的屬性,type表示它的類型,column對應的是表中的那個字段.<generator class="identity"/>
表示這個主鍵是自增長的.
③下面重頭戲閃亮登場.hibernate.cfg.xml文件
內容如下:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory name="mySessionFactory">
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/spdb3</property>
<property name="hibernate.connection.username">root</property>
<property name="connection.password">root</property>
<!-- dialect翻譯爲方言 Hibernate根據你選擇的“方言”,針對每種數據庫,作調整,如生成不同的SQL語句等 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 連接池默認配置.提供對數據庫操作速度 -->
<property name="connection.pool_size">2</property>
<!-- 自動創建|更新|驗證數據庫表結構。如果不是此方面的需求建議set value="none" -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 是否要在後臺.演示翻譯sql 語句 -->
<property name="show_sql">true</property>
<!-- 按照格式化的形式輸出 -->
<property name="format_sql">true</property>
<!-- 配置可以使用getCurrentSession
<property name="current_session_context_class">thread</property>
-->
<!-- //與實體類連接 -->
<mapping resource="com/hsp/domain/Employee.hbm.xml" />
</session-factory>
</hibernate-configuration>
這個文件的作用其實就是配置你所使用的數據庫,url,user,passwd,方言等.在這個文件中的參數有很多,我所瞭解的只是皮毛,大家可以看看代碼中的註釋.
④我自己還寫了一個獲得直接獲得Session的靜態的方法.HibernateUtil.java.內容如下
package com.hsp.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
final public class HibernateUtil {
private static SessionFactory sessionFactory=null;
//使用線程局部模式
private static ThreadLocal<Session> threadLocal=new ThreadLocal<Session>();
//私有的構造函數
private HibernateUtil() {};
static {
sessionFactory=new Configuration().configure("com/hsp/config/hibernate.cfg.xml").buildSessionFactory();
}
//獲取全新的session
public static Session openSession() {
return sessionFactory.openSession();
}
//獲取和線程關聯的session
public static Session getCurrentSession() {
Session session=threadLocal.get();
//判斷是否得到
if(session==null) {
session=sessionFactory.openSession();
//把session對象設置到threadLocal,相當於該session已經和線程綁定
threadLocal.set(session);
}
return session;
}
}
在這個類中有兩個靜態的方法,其中openSession()方法是直接獲得一個session,getCurrentSession()方法是獲得一個線程安全的session(有利於事務的處理).他們之間的具體差別我就不詳細解釋了.
⑤.下面就是一個Test.java這個的作用就是來驗證是否可以用hibernate框架來進行crud操作
package com.hsp.util;
import java.util.Date;
import java.util.List;
import com.hsp.util.*;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.*;
import com.hsp.domain.Employee;
public class TestMain {
public static void main(String[] args) {
//獲取session
Session session =HibernateUtil.getCurrentSession();
//事務
Transaction ts = null;
try {
//事務處理
ts = session.beginTransaction();
// do...
Employee emp = (Employee) session.load(Employee.class, 1);
//修改id爲1的username
emp.setUsername("dddd");
// ....doing
//事務提交
ts.commit();
} catch (Exception e) {
//如果出錯,回滾數據
if (ts != null) {
ts.rollback();
}
throw new RuntimeException(e.getMessage());
} finally {
// 關閉session
if (session != null && session.isOpen()) {
session.close();
}
}
}
}
ok,在這裏給初學者普及一下事務這個概念.比如銀行轉轉,你從農行的一個賬戶中向工行的一個賬戶轉錢,其業務是這樣的,農行賬戶的錢減去100,工行賬戶的錢加100,這需要操作數據庫,將減錢和加錢的操作同時進行完成.不能減錢完成,加錢沒完成或反之這就需要事務了.它將這兩操作包裹成原子操作.要麼做完,要麼不做.當只是執行其中一個的時候,就回滾(相當於不做).