hibernate 註解@Formula解析和使用簡介
一.hibernate 註解@Formula即hibernate提取屬性也叫做計算屬性,該屬性值是一個值讀屬性,是通過使用sql語句獲取得到的,常用的是統計資料。
例如:我有一個employee實體類,該類有主鍵Id或name,月薪水(monthlySalary)等屬性(欄位),你現在有一個想法想要獲取該employee的年薪,計算方式是月薪*12個月=年薪。
上面這個是沒有加入hibernate @Formula支援的用法,現在我們加入這個註解實現:package net.ozar.exp.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="EMPLOYEE") public class Employee implements java.io.Serializable { private static final long serialVersionUID = -7311873726885796936L; @Id @Column(name="ID") private Integer id; @Column(name="FIRST_NAME", length=31) private String firstName; @Column(name="LAST_NAME", length=31) private String lastName; @Column(name="MONTHLY_SALARY") private float monthlySalary; public Employee() { } // getters and setters // ... public float getMonthlySalary() { return monthlySalary; } public void setMonthlySalary(float monthlySalary) { this.monthlySalary = monthlySalary; } /* This artificial property - as I call it - is a kind of a calculated property, but not with Hibernate derived property support - not just yet */ public float getYearlySalary() { return this.monthlySalary * 12; } }
注意到上面這個案例的@Formla的值是關聯到“MONTHLY_SALARY”而yearlySalry屬性是沒有儲存如資料庫的。package net.ozar.exp.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.annotations.Formula; @Entity @Table(name="EMPLOYEE") public class Employee implements java.io.Serializable { private static final long serialVersionUID = -7311873726885796936L; @Id @Column(name="ID") private Integer id; @Column(name="FIRST_NAME", length=31) private String firstName; @Column(name="LAST_NAME", length=31) private String lastName; @Column(name="MONTHLY_SALARY") private float monthlySalary; <span style="color:#ff0000;">@Formula</span>("MONTHLY_SALARY*12") private float yearlySalary; public Employee() { } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public float getMonthlySalary() { return monthlySalary; } public void setMonthlySalary(float monthlySalary) { this.monthlySalary = monthlySalary; } public float getYearlySalary() { return yearlySalary; } }
一些更為複雜用法如下所示,注意:最後面的customer_id=id中後面的id的值也就當前物件的id值
@Formula("(select min(l.creation_date) from Logs l where l.customer_id = id)")
private Date firstLoginDate;
二.Hibernate Formula作用就是說白了就是用一個查詢語句動態的生成一個類的屬性。
比如java eye登陸之後 收件箱顯示有幾封未讀郵件的數字,就是一條select count(*)...構成的虛擬列,而不是儲存在資料庫裡的一個欄位。
用比較標準的說法就是:有時候,你想讓資料庫,而非JVM,來替你完成一些計算,也可能想建立某種虛擬列,你可以使用sql片段,而不是將屬性對映(物理)列。這種屬性是隻讀的(屬性值由公式求得).Formula甚至可以包含sql子查詢,Formula真的這麼強大嗎?確實,它很好很強大,節省了不少程式碼!
使用Formula的細節:
package aa;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Formula;
/**
* 註解必須是在屬性上的,如果有任何一個註解在方法上,那麼@Formula將失效
* @author 昆明蜂鳥軟體
* @version 0.1.0 2008-7-15 下午06:09:38
*/
@Entity
@Table(name = "user", catalog = "test")
public class User {
@Id
@GeneratedValue(strategy = IDENTITY)
private int id;
@Formula("(select COUNT(*) from user)")
private int count;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
資料庫表:Sql程式碼
CREATE TABLE `test`.`user` (
`id` int(10) unsigned NOT NULL auto_increment,
PRIMARY KEY USING BTREE (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
細節1.使用@Formula 你的註解必須是在屬性上,如果有一個註解在方法上,那麼@Formula將失效。
這個我是做過實驗的,比如把以上的java檔案改為:
package aa;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Formula;
/**
* 註解必須是在屬性上的,如果有任何一個註解在方法上,那麼@Formula將失效
* @author 昆明蜂鳥軟體
* @version 0.1.0 2008-7-15 下午06:09:38
*/
@Entity
@Table(name = "user", catalog = "test")
public class User {
private int id;
@Formula("(select COUNT(*) from user)")
private int count;
<span style="color:#3333FF;">@Id
@GeneratedValue(strategy = IDENTITY)
public int getId() {
return id;
} </span>
public void setId(int id) {
this.id = id;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
這樣@Formula就不可以執行!!!我前邊就是被Hibernate官方的文件給搞暈了。
細節2.既然@Formula 是一個虛擬列,那麼資料庫中不需要建這一列,同樣可以,如果有個列存在,hibernate也會將 其忽略。
以上示例中的user就沒有count列。
細節3.sql語句必須寫在()中,這個以前也有人說過。
細節4.如果有where子查詢,那麼表需要用別名,比如 select COUNT(*) from user where id=1 是錯的
而select COUNT(*) from user u where u.id=1是正確的
細節5.只要是你在資料庫的sql控制檯執行過的語句,並且使用了表別名,那麼@Formula都應該是支援的。
確實@Formula是一個很常用且好用的東西!