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ù)庫中沒有記錄。
- 持久化狀態(tài):實(shí)體對(duì)象在數(shù)據(jù)庫中有記錄,并且有session管理。
- 游離狀態(tài):實(shí)體對(duì)象在數(shù)據(jù)庫中有記錄,但是對(duì)應(yīng)的session已經(jīng)關(guān)閉。
HIbernate的三種查詢:
- 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();
......
- 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();
......
- 使用標(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)
- all:所有的數(shù)據(jù)庫操作都執(zhí)行級(jí)聯(lián)操作
- none:所有的數(shù)據(jù)庫操作都不執(zhí)行級(jí)聯(lián)操作
- delete:刪除操作執(zhí)行級(jí)聯(lián)操作
- 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