Hibernate

Hibernate中常用的注解
@Entity表示該類是持久化類
@Table表示將該類映射到對(duì)應(yīng)的表
@Id表示主鍵ID
@GenerateValue表示主鍵生成策略
@Column表示屬性和字段的映射
@Transient表示忽略該屬性
@OneToMany表示一對(duì)多
@ManyToOne表示多對(duì)一
@ManyToMany表示多對(duì)多
@OneToOne表示一對(duì)一
如果不想使用id作為主鍵,可以使用例如下面的這種方式

<property name="屬性名稱" type=“類型” column=“數(shù)據(jù)庫字段名稱”>
    <generator class="assigned">
</property>
assigned表示主鍵由用戶決定

@OneToMany一對(duì)多單向配置時(shí):

package com.how2java.hibernateTest;

import org.hibernate.annotations.Entity;

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "Category")
public class Category {

    private Long id;
    private String type;
    private List<Product> products;


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
    @Column(name = "type")
    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @OneToMany(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    @JoinColumn(name = "cid")//name使用的是數(shù)據(jù)庫字段名
    public List<Product> getProducts() {
        return products;
    }

    public void setProducts(List<Product> products) {
        this.products = products;
    }
}

package com.how2java.hibernateTest;

import org.hibernate.annotations.Entity;

import javax.persistence.*;

@Entity
@Table(name = "Product_")
public class Product {

    private Long id;
    private String name;
    private Double price;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "price")
    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}

@OneToMany雙向配置

package com.how2java.hibernateTest;

import org.hibernate.annotations.Entity;

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "Category")
public class Category {

    private Long id;
    private String type;
    private List<Product> products;


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }
    @Column(name = "type")
    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
//mappedBy表示在多的一方Category的屬性名,防止生成中間表
    @OneToMany(cascade = CascadeType.ALL,mappedBy = "category")
    public List<Product> getProducts() {
        return products;
    }

    public void setProducts(List<Product> products) {
        this.products = products;
    }
}

package com.how2java.hibernateTest;

import org.hibernate.annotations.Entity;
import org.hibernate.annotations.ManyToAny;

import javax.persistence.*;

@Entity
@Table(name = "Product_")
public class Product {

    private Long id;
    private String name;
    private Double price;
    private Category category;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @Column(name = "name")
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Column(name = "price")
    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @ManyToOne
    @JoinColumn(name = "cid",referencedColumnName = "id") //name表示在本表中的數(shù)據(jù)庫字段名,referencedColumnName表示對(duì)應(yīng)的在連接的表中的數(shù)據(jù)庫字段名
    @Basic(fetch=FetchType.LAZY)
    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }
}

Hibernate中的Session接口是Hibernate向應(yīng)用程序提供數(shù)據(jù)庫操作的主要接口,它提供了基本的增刪改查java對(duì)象的方法。
Session中的緩存:
session緩存是hibernate的一級(jí)緩存,Session緩存可以減少Hibernate應(yīng)用訪問數(shù)據(jù)庫的頻率。
session中的flush():將緩存中的對(duì)象屬性變化更新數(shù)據(jù)庫中的記錄,使緩存中的對(duì)象和數(shù)據(jù)庫記錄保持一致。
調(diào)用flush()的時(shí)間點(diǎn)有:
1.手動(dòng)調(diào)用flush()方法
2.事務(wù)提交的時(shí)候,會(huì)首先調(diào)用flush()方法,然后再提交事務(wù)
3.當(dāng)程序執(zhí)行一些查詢操作的時(shí)候,如果緩存中的對(duì)象的屬性已經(jīng)發(fā)生變化,會(huì)先調(diào)用flush()方法,將變化更新到數(shù)據(jù)庫中,以保證查詢的對(duì)象屬性是最新的。
session中的refresh()方法:刷新緩存中的數(shù)據(jù)
session中的clear()方法:清除緩存

實(shí)體對(duì)象在hibernate中的三種狀態(tài):
1 . 臨時(shí)狀態(tài):對(duì)象創(chuàng)建出來,沒有session管理,數(shù)據(jù)庫中沒有記錄。

  1. 持久化狀態(tài):實(shí)體對(duì)象在數(shù)據(jù)庫中有記錄,并且有session管理。
  2. 游離狀態(tài):實(shí)體對(duì)象在數(shù)據(jù)庫中有記錄,但是對(duì)應(yīng)的session已經(jīng)關(guān)閉。

HIbernate的三種查詢:

  1. HQL(HIbernate Query Language):Hibernate專門的查詢語言
    是使用類名而不是表名,不需要寫select *,
    例如:
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
String name = "iphone";
Query q = session.createQuery(' from Product p where p.name like ? ');//Product使用的是類名
q.setString(0,"%" + name + "%" );
List<Product> products = q.list();
......
  1. Criteria查詢完全是面向?qū)ο蟮?,完全看不到語句
    例如:
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
String name = "iphone";
Criteria c = s.createCriteria(Product.class);
c.add(Restrictions.like("name","%"+name+"%"));
List<Product> products = c.list();
......
  1. 使用標(biāo)準(zhǔn)的SQL語句進(jìn)行查詢
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
String name = "iphone";
String sql = "select * from product_ p where  p.name like "%"+name+"%"";
Query q = session.createSqlQuery(sql);
List<Product> products = q.list();
......

HIbernate事務(wù):
Hibernate中任何對(duì)數(shù)據(jù)進(jìn)行改動(dòng)的操作都應(yīng)該放在事務(wù)中。一個(gè)事務(wù)中,多個(gè)操作要么都成功,要么都失敗。
事務(wù)是由Session的beginTransaction()開始,由Session的getTransaction().commit()結(jié)束。
HIbernate延遲加載:
屬性延遲加載:使用load()方法取對(duì)象的時(shí)候,如果不訪問對(duì)象的屬性,是不會(huì)去數(shù)據(jù)庫中查找該對(duì)象。只有在訪問該對(duì)象的屬性的時(shí)候,才會(huì)去數(shù)據(jù)庫中查找該對(duì)象。
關(guān)系延遲加載:在一對(duì)多或多對(duì)多關(guān)系中可以設(shè)置延遲加載,在取多的對(duì)象的時(shí)候才去查數(shù)據(jù)庫加載。
HIbernate級(jí)聯(lián):
如果配置了級(jí)聯(lián),簡(jiǎn)單的說就是刪除一個(gè)一方時(shí),其對(duì)應(yīng)的多的一方也會(huì)被刪除。
有四種類型的級(jí)聯(lián)

  1. all:所有的數(shù)據(jù)庫操作都執(zhí)行級(jí)聯(lián)操作
  2. none:所有的數(shù)據(jù)庫操作都不執(zhí)行級(jí)聯(lián)操作
  3. delete:刪除操作執(zhí)行級(jí)聯(lián)操作
  4. save-update:執(zhí)行級(jí)聯(lián)操作
    默認(rèn)是none
    Hibernate的一級(jí)緩存和二級(jí)緩存:
    Hibernate的一級(jí)緩存:默認(rèn)開啟一級(jí)緩存,一級(jí)緩存放在session上
    例如:
public static void main(String[] args){
       SessionFactory sf = new Configuration().configure().buildSessionFactory();

       Session s = sf.openSession();
       s.beginTransaction();
       Category p1 = (Category) s.get(Category.class, 1);
       Category p2 = (Category) s.get(Category.class, 1);
       s.getTransaction().commit();
       s.close();
       Session s2 = sf.openSession();
       s2.beginTransaction();
       Category p3 = (Category) s2.get(Category.class, 1);

       s2.getTransaction().commit();
       s2.close();
       sf.close();
   }
上面的代碼中,獲取p1的時(shí)候會(huì)執(zhí)行sql查詢,獲取p2的時(shí)候不執(zhí)行sql直接從緩存中取,獲取p3的時(shí)候執(zhí)行sql,因?yàn)樗鼈儾皇峭粋€(gè)session

Hibernate二級(jí)緩存:
二級(jí)緩存是放在SessionFactory上,二級(jí)緩存需要使用第三方插件開啟
上面的代碼中,只有在獲取p1的時(shí)候執(zhí)行sql查詢,獲取p2、p3的時(shí)候都不需要執(zhí)行sql查詢,直接從緩存中取。

Hibernate的分頁:
使用Criteria的setFirstResult和setMaxResults實(shí)現(xiàn)分頁

SessionFactory sf = new Configuration().configure().buildSessionFactory();

       Session s = sf.openSession();
       s.beginTransaction();
       Criteria criteria = s.createCriteria(Category.class);
       criteria.add(Restrictions.like("name","%"+"iphone"+"%"));
       criteria.setFirstResult(3);    //從第4條開始
       criteria.setMaxResults(5);  //一共查詢5條數(shù)據(jù)

Hibernate中的load和get的區(qū)別:
get不會(huì)延遲加載,會(huì)立即執(zhí)行查詢,當(dāng)查詢對(duì)象不存在的時(shí)候,返回null
load會(huì)延遲加載,在訪問對(duì)象的屬性或方法的時(shí)候,才去查詢對(duì)象,當(dāng)查詢對(duì)象不存在的時(shí)候,會(huì)報(bào)錯(cuò)。
Hibernate中兩種獲取session的方式:
openSession():每次都會(huì)獲取一個(gè)新的session,查詢操作不需要事務(wù),其他操作需要事務(wù)。
getCurrentSession():在同一個(gè)線程中,每次獲取的都是同一個(gè)session,增刪改查操作都需要事務(wù)。事務(wù)提交之后會(huì)自動(dòng)關(guān)閉。
Hibernate的樂觀鎖:
當(dāng)多個(gè)用戶同時(shí)修改某個(gè)數(shù)據(jù)的時(shí)候,就會(huì)出現(xiàn)問題,這個(gè)時(shí)候可以給對(duì)象上添加version字段,用于版本控制,version字段必須緊挨著id字段。
當(dāng)一個(gè)用戶修改了數(shù)據(jù)庫對(duì)象的時(shí)候,相應(yīng)的version也會(huì)改變,當(dāng)另一個(gè)已經(jīng)獲取version改變前的對(duì)象,進(jìn)行修改操作的時(shí)候會(huì)和數(shù)據(jù)庫中該對(duì)象當(dāng)前的version進(jìn)行比較,如果version不等于數(shù)據(jù)庫中該對(duì)象當(dāng)前的version,操作就會(huì)失敗。

深入理解session中的flush()方法:
例如:

SessionFactory sf = new Configuration().configure().buildSessionFactory();

        Session s = sf.openSession();
        s.beginTransaction();

        Product o = (Product) s.get(Product.class, 1);     //從數(shù)據(jù)庫中查id為1的product
        System.out.println(o.getName());          //會(huì)把查詢結(jié)果保存到session中
        o.setName("iphone7");                    
        s.flush();                //準(zhǔn)備執(zhí)行update操作
        System.out.println(o.getName());       //獲取到的是更新后的名字
        Product o1 = (Product) s.get(Product.class, 1);   //從session中獲取
        System.out.println(o1.getName());

輸出為:
Hibernate: select product0_.id as id0_0_, product0_.name as name0_0_, product0_.price as price0_0_ from product_ product0_ where product0_.id=?
iphone
Hibernate: update product_ set name=?, price=? where id=?
iphone7
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容