實體類規範(javaBean規範)
1.提供無參構造方法
2.成員變量私有化提供get/set方法
double 表示學分 0-100.0 沒考試 0
Double 有null值 缺考 用空值表示0分
3.基本數據類型儘量使用包裝類型(可以多表示一個值null例如考試分數 缺考和0分)
4.實體中必須要提供一個與表中的主鍵相對應的屬性id
hibernate是通過主鍵來區別對象是否相同
5.不要使用final修飾實體類(代理對象是要繼承該類的)
主鍵的類型
1.自然主鍵
輸入人的時候 人的身份證號 保證了 非空不重複 複合主鍵的貼點
但是身份證號 本身是業務字段 可以作爲主鍵使用 叫做自然主鍵
2.代理主鍵(常用)
當找不到主鍵的時候(沒有業務字段符合主鍵的規則)
搞一個沒有任何意義的主鍵id列 作爲主鍵 就是爲了非空不重複 叫做代理主鍵
主鍵生成策略(7種)
identity:主鍵自增 有數據庫來維護主鍵 錄入的時候不需要指定主鍵
increment:主鍵自增 由hibernate來維護主鍵 每次插入前會先查詢表中 id
最大值 +1 作爲新主鍵
效率不高每次都要查詢 如何10個人同時要保存 可能會出現線程問題
sequence:Oracle中的主鍵生策略 序列
hilo:高低位算法(數據庫中的主鍵自增算法原理)由hiernate來維護主鍵hibernate自己算一下(無意義)
native:hilo +sequence + identity 自動三選一 檢測你是什麼數據庫
mysql就identity Oracle就sequence 如果沒有就 用hilo 但是世界上沒有一個 不支持自增和序列的數據庫 其實就是2 選1
uuid:產生一個隨機的字符串作爲主鍵 主鍵類型必須爲string類型
assigned:自然主鍵生成策略(沒策略)hibernate不會管理 由開發人自己錄入
三種狀態
1.瞬時態 沒有id 沒有和session關聯(這裏的關聯是指和緩存關聯)
2.持久態 有id 有關聯(這裏的關聯是指和緩存關聯)
3.遊離態 有id 沒有關聯(這裏的關聯是指和緩存關聯)
測試:save get 多次 打印的語句
結論:就是將我們想要同步數據庫的數據 所對應的對象轉換成持久態
/* hibernate中對象的三種狀態
*
*/
@Test
public void fun(){
//獲取session
Session session = HibernateUtils.getSession();
//開啓事物
Transaction transaction = session.beginTransaction();
//包裹語句
//*******************************
User user = new User(); //瞬時態 沒有id 沒有和session關聯
user.setUsername("wl");
user.setPassword("123456");
session.save(user); //持久態 有id 有和session關聯
// update delete get 這三個方法是從 什麼態 轉 成什麼態
//*********************************
//提交事務
transaction.commit();
//關閉資源
session.close(); //遊離態 有id 沒有和session關聯
}
一級緩存與快照(系統實現的 將以下的實現的原理)
1一級緩存測試 get多次 打印的語句
@Test
public void fun2(){
//獲取session
Session session = HibernateUtils.getSession();
//開啓事物
Transaction transaction = session.beginTransaction();
//包裹語句
//*******************************
//測試一下hibernate 中的緩存
User user1 = session.get(User.class, 1);
User user2 = session.get(User.class, 1);
User user3= session.get(User.class, 1);
User user4 = session.get(User.class, 1);
User user5 = session.get(User.class, 1);
//1.生成幾條sql語句
//2.下面打印的結果
//思考:爲什麼?
//hibernate 的緩存機制
//第一次 再一次
System.out.println(user2==user5);
//*********************************
//提交事務
transaction.commit();
//關閉資源
session.close(); //遊離態 有id 沒有和session關聯
}
2.快照 測試 get後 修改兩次名字 打印的語句
@Test
//快照測試
public void fun4(){
//獲取session
Session session = HibernateUtils.getSession();
//開啓事物
Transaction transaction = session.beginTransaction();
//包裹語句
//*********************************
User user = session.get(User.class, 1);
user.setUsername("pp");
user.setUsername("dpp");
session.update(user);
//*********************************
//提交事務
transaction.commit();
//關閉資源
session.close(); //遊離態 有id 沒有和session關聯
}
3.測試
瞬時態 -> 遊離態->持久態
new對象 -> 設置id -> update -> get
事物
Transaction transaction = session.beginTransaction();
//包裹語句
//*********************************
User user = new User();//瞬時態 沒有id 和session中的緩存 沒有關聯
user.setId(1); // 遊離態 有id 和session中的緩存 沒有關聯
//從數據庫返回結果集 是保存進緩存和快照中
//update 時 把這個要更新的對象 放入緩存中(跟快照沒關係)
session.update(user); //持久態 有id 和session中的緩存 有關聯
//get查詢時 去緩存中 查找 看有沒有該id的對象
User u = session.get(User.class, 1);
//問:打印幾條語句 爲什麼
//*********************************
//當事物提交的時候
//hibernate 會 對比 快照 和緩存中的對象是否相同
//不相同 會把緩存中的對象 同步到數據庫
//提交事務
transaction.commit();
//關閉資源
session.close(); //遊離態 有id 沒有和session關聯
}
指定事物的隔離級別
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate配置根標籤 -->
<hibernate-configuration>
<!-- session-factory 相當於數據庫連接池 -->
<session-factory>
<!-- 加載了數據庫的驅動類 基礎設置 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/a_hibernate_01</property>
<!-- hibernate方言 配置使用哪個類 全限定類名 org.hibernate.dialect.MySQLDialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 在控制檯輸出sql語句 -->
<property name="hibernate.show_sql">true</property>
<!-- 美化sql語句 -->
<property name="hibernate.format_sql">true</property>
<!-- hbm2ddl.auto 是否自動生成表結構 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<!--
通過hibernate 來設置事物的隔離級別
## specify a JDBC isolation level
#hibernate.connection.isolation 1|2|4|8
隔離級別是用一個字節存儲的
0001 1
0010 2
0100 4
1000 8 -->
<property name="hibernate.connection.isolation">4</property>
<!-- 使用getCurrentSession 必須配置一下 -->
<!-- 注意當你使用 getCurrentSession時 不需要你手動關閉session 系統會幫你關閉 -->
<property name="hibernate.current_session_context_class">thread</property>
1.髒讀
2.可重複讀
3.幻讀
READ UNCOMMITTED 讀未提交 1 2 3
READ COMMITTED 讀已提交 2 3
REPEATABLE READ 可重複讀 3
SERIALIZABLE 串行化(只能一個一個的訪問:效率非常的低)
-->
<!-- 注意:映射實體類 全文件名 從包名開始 -->
<!-- 讓配置文件知道有你這個實體類 -->
<mapping resource="com/lanou3g/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
設置可以獲取當前session 與當前線程綁定的
1.thread
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<!-- hibernate配置根標籤 -->
<hibernate-configuration>
<!-- session-factory 相當於數據庫連接池 -->
<session-factory>
<!-- 加載了數據庫的驅動類 基礎設置 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/a_hibernate_01</property>
<!-- hibernate方言 配置使用哪個類 全限定類名 org.hibernate.dialect.MySQLDialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 在控制檯輸出sql語句 -->
<property name="hibernate.show_sql">true</property>
<!-- 美化sql語句 -->
<property name="hibernate.format_sql">true</property>
<!-- hbm2ddl.auto 是否自動生成表結構 -->
<property name="hibernate.hbm2ddl.auto">update</property>
<property name="hibernate.connection.isolation">4</property>
<!-- 使用getCurrentSession 必須配置一下 -->
<!-- 注意當你使用 getCurrentSession時 不需要你手動關閉session 系統會幫你關閉 -->
<property name="hibernate.current_session_context_class">thread</property>
<!-- 注意:映射實體類 全文件名 從包名開始 -->
<!-- 讓配置文件知道有你這個實體類 -->
<mapping resource="com/lanou3g/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
注意:
1.配置配置文件
2.調用getCurrentSession獲取session 當事務提交 session會自動關閉 不需要手動關閉
創建實體類
public class User {
private int id;
private String username;
private String password;
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(int id, String username, String password) {
super();
this.id = id;
this.username = username;
this.password = password;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", password=" + password + "]";
}
}
簡單的分裝一個獲取session的方法
/*
* 簡單封裝
*/
public class HibernateUtils {
// 把sessionFactory寫成成員變量
private static SessionFactory sessionFactory;
static {
// 加載配置文件
Configuration configuration = new Configuration().configure();
// 創建session工廠
sessionFactory = configuration.buildSessionFactory();
}
// 返回session的方法
public static Session getSession() {
return sessionFactory.openSession();
}
// 返回當前session的方法
public static Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
獲取session
public class UserDao {
public void saveUser(User user) {
//獲取當前的session
Session session = HibernateUtils.getCurrentSession();
session.save(user);
}
}
獲取當前的session
public class UserService {
private UserDao dao = new UserDao();
public void addUser(User user) {
//獲取當前的session
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//調用dao層方法失敗了怎麼辦?
try {
dao.saveUser(user);
} catch (Exception e) {
//可以使用異常來處理. 失敗之後會報個異常.
e.printStackTrace();
//直接回滾事物 rollback
transaction.rollback();
}
transaction.commit();
}
}