Hibernate

hibernate簡介
Hibernatehibernate簡介
hibernate快速入門
session查詢api
實體類的三種狀態
關聯關系多對一
一對多
多對多

hibernate常用查詢api
hibernate緩存一級緩存
二級緩存
查詢緩存

OpenSessionInView1、創建一個工具類HIbernateUtils
2、創建一個過濾器OpenSessionInViewFilter
3、在hibernate.cfg.xml中配置屬性

jpa基本用法
多對一
一對多
多對多

hibernate-validator

Hibernate
概念:
作用:
特點:

hibernate快速入門
導包

Some_Text

配置文件

<!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.url">jdbc:mysql://localhost:3306/hibernate</property>
    <property name="hibernate.connection.username">root</property>
    <property name="hibernate.connection.password"></property>
    <!-- SQL 方言 ,注意使用MySQLInnoDBDialect,才可以使用Innodb引擎-->
    <property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
    <!-- 打印出sql -->
    <property name="show_sql">true</property>       
    <!-- 格式化sql -->
    <property name="format_sql">true</property>
    <!-- 有表更新表,沒有表自動創建表 -->
    <property name="hbm2ddl.auto">update</property>     
    <!-- 加載映射文件 -->
    <mapping resource="User.hbm.xml"/>
</session-factory>
</hibernate-configuration>

注意:主配置文件名,一般默認是hibernate.cfg.xml,并且在src根目錄中 上面的配置文件,可以參考etc文件夾下的配置文件



創建類

public class User {
private int uid;
private String username;
private String password;
//get/set方法 必須要有
}

映射文件

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">  
<hibernate-mapping>
<class name="com.hibernate.entity.User" table="user">
    <id name="uid" column="uid">
        <!-- 使用數據庫默認的生成主鍵的方案 -->
        <generator class="native"/>
    </id>
    <property name="username" column="username"/>
    <property name="password" column="password"/>
</class>
</hibernate-mapping>


 Configuration configure = new Configuration().configure("hibernate.cfg.xml");
SessionFactory factory = configure.buildSessionFactory();
Session session = factory.openSession();// 獲取連接
// 開啟事務
Transaction tx = session.beginTransaction();
User user = new User("黃蓉", "123");
session.save(user);
tx.commit();// 提交事務
session.close();// 關閉連接

session查詢api
save、delete、update
get 不支持延遲查詢
load 延遲查詢:如果使用了對象中非id的屬性時才會發送sql語句
saveOrUpdate
瞬時態執行save(),游離態執行update()
merge
兩個相同id的對象合并

實體類的三種狀態
瞬時態:無id,與session無關聯,與數據庫無關聯
持久態:有id,與session有關聯,與數據庫關聯 持久態對象修改數據,會自動修改數據庫的數據
游離態(離線):有id,與session無關聯,與數據庫有關


具體請看hibernate的三種狀態

關聯關系

多對一
多個Customer對應一個User


一對多
一個User對應多個Customer



注意:一對多,多對一其實是從不同角度看問題,本質是一樣的,任意寫一個就是單向的一對多(多對一),兩個都寫,就是雙向的一對多(多對一)。單向意味著,只能從一方找到另一方,雙方可以相互找到對方。

多對多


hibernate常用查詢api
詳情請點擊這里

hibernate緩存

一級緩存
第一次查找,去緩存中找,沒有數據,從數據庫獲取,然后存入一級緩存,并且存入快照區;session沒有關閉,并且執行第二次查找,先從一級緩存中獲取。如果對象修改了數據,一級緩存中的數據也修改了,那么會將一級緩存和快照區的數據進行比對,如果不相同,就將數據存入數據庫。
第一級別的緩存是 Session 級別的緩存,它是屬于事務范圍的緩存(session的一級緩存)
更多詳情請查看

二級緩存
二級緩存屬于SessionFactory級別的緩存,緩存的對象根據提供的實現類不同,放置的位置也不同,主要就是內存和硬盤中。二級緩存是緩存對象的Id,所以只有通過id查詢的,二級緩存才能生效。
第二級別的緩存是 SessionFactory 級別的緩存,它是屬于進程范圍的緩存
二級緩存的實現有很多,我們使用ehcache來實現二級緩存
1、導包

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-ehcache</artifactId>
        <version>5.0.12.Final</version>
    </dependency>

    <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache-core</artifactId>
        <version>2.6.11</version>
    </dependency>

2、在spring-hibernate.xml中配置

    <!-- 開啟二級緩存:根據id來查詢 -->
  <prop key="hibernate.cache.use_second_level_cache">true</prop>
  <!-- 開啟查詢緩存:根據非id來查詢,需要在query中設置setCacheable(true) -->
  <prop key="hibernate.cache.use_query_cache">true</prop>
  <!-- 高速緩存提供程序 -->
  <prop       key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>

3、在resources根目錄中添加ehcache.xml文件

  <ehcache>  
  <!--
  指定二級緩存存放在磁盤上的位置,可以使用磁盤目錄
    也可以使用Java System Property目錄
    user.home是用戶目錄
    user.dir是用戶當前工作目錄
    java.io.tmpdir是默認臨時文件路徑
  -->
<diskStore path="java.io.tmpdir/cache"/>

<!-- ehcache將緩存分為多個不同的區域,不同的區域可以設置不同的緩存策略 -->

<!--緩存策略:
    name:Cache的唯一標識。
    maxElementsInMemory:內存中最大緩存對象數。
    eternal:Element是否永久有效,一旦設置true,timeout將不起作用。
    timeToIdleSeconds:設置Element在失效前的允許閑置時間。僅當element不是永久有效時使用,可選屬性,默認值是0,也就是可閑置時間無窮大。
    timeToLiveSeconds:設置Element在失效前允許存活時間。最大時間介于創建時間和失效時間之間。僅當element不是永久有效時使用,默認是0.,也就是element存活時間無窮大。
    overflowToDisk:配置此屬性,當內存中Element數量達到maxElementsInMemory時,Ehcache將會Element寫到磁盤中。
    maxElementsOnDisk:磁盤中最大緩存對象數,若是0表示無窮大。
    memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略
    去清理緩存中的內容。默認策略是LRU(最近最少使用),你也可以設置為FIFO(先進先出)或是LFU(較少使用) -->
  
<defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
/>

<cache name="simple"
       maxElementsInMemory="1000"
       eternal="true"
       timeToIdleSeconds="0"
       timeToLiveSeconds="0"
       overflowToDisk="false"
/>

<!--可以給每個實體類指定一個配置文件,通過name屬性指定,要使用類的全名-->
<!--<cache name="com.study.entity.User"-->
<!--maxElementsInMemory="10000"-->
<!--eternal="false"-->
<!--timeToIdleSeconds="300"-->
<!--timeToLiveSeconds="600"-->
<!--overflowToDisk="true"-->
<!--/>-->

</ehcache>
4、在需要使用二級緩存的類上添加注解

//region:標示要使用的區域,不同的區域使用的緩存策略不一樣,見上面第3點說明
//usage:指定使用的并非策略
@org.hibernate.annotations.Cache(region ="simple",usage =     CacheConcurrencyStrategy.READ_ONLY)

ehcache的四種緩存并發策略如下:
read-write(讀寫型)
提供Read Committed事務隔離級別
在非集群的環境中適用
適用經常被讀,很少修改的數據
可以防止臟讀
更新緩存的時候會鎖定緩存中的數據

nonstrict-read-write(非嚴格讀寫型)
適用極少被修改,偶爾允許臟讀的數據(兩個事務同時修改數據的情況很少見)
不保證緩存和數據庫中數據的一致性
為緩存數據設置很短的過期時間,從而盡量避免臟讀
不鎖定緩存中的數據

read-only(只讀型)
適用從來不會被修改的數據(如參考數據)
在此模式下,如果對數據進行更新操作,會有異常
事務隔離級別低,并發性能高
在集群環境中也能完美運作

5、測試

   AppInfo appInfo = appInfoService.findOneById(1);
    System.out.println(appInfo);

    AppInfo appInfo1 = appInfoService.findOneById(1);
    System.out.println(appInfo1);

注意:
1、list()只查詢一級緩存,而iterator()會從二級緩存中查
2、list()方法返回的對象都是實體對象,而iterator()返回的是代理對象

查詢緩存
Query Cache只是在特定的條件下才會發揮作用,而且要求相當嚴格:
完全相同的HQL重復執行。(注意,只有hql)
重復執行期間,Query Cache對應的數據表不能有數據變動(比如添、刪、改操作)

絕大多數的查詢并不能從查詢緩存中受益,所以Hibernate默認是不進行查詢緩存的。查詢緩存適用于以下場合:
在應用程序運行時經常使用的查詢語句(參數相同)
很少對與查詢語句檢索到的數據進行插入、刪除或更新操作

  Query query = session.createQuery(hql);     
  query.setCacheable(true); //啟用查詢緩存  
  query.setCacheRegion(“queryCacheRegion”); //設置查詢緩存區域(數據過期策略)  
  query.list();  
  OpenSessionInView

1、創建一個工具類HIbernateUtils

   private static SessionFactory factory;
static {
     factory = new Configuration().configure().buildSessionFactory();
}

public static Session getSession() {
    return factory.getCurrentSession();//將session與線程綁定
}

2、創建一個過濾器OpenSessionInViewFilter

   Session session = HibernateUtils.getSession();
    Transaction tx = null;
    try {
        tx = session.beginTransaction();
        chain.doFilter(request, response);
        tx.commit();
    } catch (Exception e) {
        e.printStackTrace();
        if (tx != null) {
            tx.rollback();
        }
    } finally {
        if (session != null) {
            session.close();
        }
    }

3、在hibernate.cfg.xml中配置屬性

  <property name="hibernate.current_session_context_class">thread</property> 

request(請求)->open session并開始transaction->controller->View(Jsp)->結束transaction并 close session.
有可能在chain.doFilter()被阻塞,因為有可能輸出jsp的頁面內容大,response.write的時間長,另一方面可能是網速慢,服務器與用戶間傳輸時間久。當大量這樣的情況出現時,就有連接池連接不足,造成頁面假死現象。

jpa
什么是jpa
java persistence api,java在持久層的一套接口,與jdbc接口類似,提供一套規范,有其他數據庫廠商去實現
hibernate實現了jpa接口


基本用法



@Entity //表示該類為持久化類
@Table(name="user") //對應數據庫的表名
public class User {
@Id //主鍵
@GeneratedValue(strategy=GenerationType.IDENTITY)//主鍵生成策略 IDENTITY與native類似
private Integer uid;
@Column(name="user_name") //設置屬性名與字段名的映射關系
private String username;
private String password; //如果屬性名與字段名一致,可以不寫注解

}
注意:如果下面的注解不理解,請看上面xml配置映射關系的圖

多對一

@ManyToOne(cascade=CascadeType.ALL) //casacde為級聯
@JoinColumn(name="uid") //外鍵
private User user;

一對多

在一方設置@OneToMany和@JoinColumn

@OneToMany(cascade=CascadeType.ALL) //casacde為級聯
@JoinColumn(name="uid") //外鍵
private Set<Customer> custSet = new HashSet<>();

多對多
在任意一方設置@ManyToMany和@JoinTable

@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@JoinTable(//生成第三張表
        name="role_user",
        joinColumns={@JoinColumn(name="uid")},//本表中的主鍵
        inverseJoinColumns={@JoinColumn(name="rid")}//另一張表的主鍵
)
private Set<Role> roleSet = new HashSet<>();

雙向的只要在另一個類中寫同樣的注解即可

@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@JoinTable(
        name="role_user",
        joinColumns={@JoinColumn(name="rid")},//本表中的主鍵
        inverseJoinColumns={@JoinColumn(name="uid")}//另一張表的主鍵
)
private Set<User> userSet = new HashSet<>();

hibernate-validator
springmvc整合validator
1、導包,注意要4.xx的版本

 <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>4.3.1.Final</version>
    </dependency>

2、在springmvc中配置

  <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="providerClass" value="org.hibernate.validator.HibernateValidator" />
</bean>
<mvc:annotation-driven validator="validator">

4、在類上添加注解

   //Bean Validation 中內置的 constraint
  @Null   //被注釋的元素必須為 null    
@NotNull    //被注釋的元素必須不為 null    
@AssertTrue     //被注釋的元素必須為 true    
@AssertFalse    //被注釋的元素必須為 false    
@Min(value)     //被注釋的元素必須是一個數字,其值必須大于等于指定的最小值    
@Max(value)     //被注釋的元素必須是一個數字,其值必須小于等于指定的最大值    
@DecimalMin(value)  //被注釋的元素必須是一個數字,其值必須大于等于指定的最小值    
@DecimalMax(value)  //被注釋的元素必須是一個數字,其值必須小于等于指定的最大值    
@Size(max=, min=)   //被注釋的元素的大小必須在指定的范圍內    
@Digits (integer, fraction)     //被注釋的元素必須是一個數字,其值必須在可接受的范圍內    
@Past   //被注釋的元素必須是一個過去的日期    
@Future     //被注釋的元素必須是一個將來的日期    
@Pattern(regex=,flag=)  //被注釋的元素必須符合指定的正則表達式    

//Hibernate Validator 附加的 constraint    
@NotBlank(message =)   //驗證字符串非null,且長度必須大于0    
@Email  //被注釋的元素必須是電子郵箱地址    
@Length(min=,max=) @Range用法一致 //被注釋的字符串的大小必須在指定的范圍內    
@NotEmpty   //被注釋的字符串的必須非空    
@Range(min=,max=,message=)  //被注釋的元素必須在合適的范圍內

5、springmvc

    @RequestMapping("doAdd")
    public String doAdd(Model model,
           @RequestParam(name = "img", required = false) MultipartFile multipartFile,
           @Valid AppInfo appInfo, BindingResult bindingResult 
          //@Valid必須與BindingResult在一起,bindingResult放在末尾
){}

導包

 <dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>antlr</groupId>
        <artifactId>antlr</artifactId>
        <version>2.7.7</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml</groupId>
        <artifactId>classmate</artifactId>
        <version>1.3.4</version>
    </dependency>
    <dependency>
        <groupId>dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>1.6.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.geronimo.specs</groupId>
        <artifactId>geronimo-annotation_1.0_spec</artifactId>
        <version>1.0</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.common</groupId>
        <artifactId>hibernate-commons-annotations</artifactId>
        <version>5.0.1.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.0.12.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.javax.persistence</groupId>
        <artifactId>hibernate-jpa-2.1-api</artifactId>
        <version>1.0.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jboss</groupId>
        <artifactId>jandex</artifactId>
        <version>2.0.0.Final</version>
    </dependency>
    <dependency>
        <groupId>jboss</groupId>
        <artifactId>javassist</artifactId>
        <version>3.7.ga</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.logging</groupId>
        <artifactId>jboss-logging</artifactId>
        <version>3.3.1.Final</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.30</version>
    </dependency>
</dependencies>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容