Hibernate持久層框架使用【四】hibernate的常用註解
@DynamicInsert註解
這是一個hibernate對類的註解,用於資料的動態插入,對於持久化類中的屬性是否被賦值來動態生成sql語句
例如下面使用該註解來註解User類
@Entity(name="tb_user") @DynamicInsert(false) public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_id") private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
新建一個類用於測試這個註解,例如這裡為table.class
這裡的MySessionFactory類為自定義的工具類,參考前面的博文
public class table { public static void main(String[] args) { // TODO Auto-generated method stub MySessionFactory mySessionFactory = new MySessionFactory(); Session session = mySessionFactory.getSession(); User user = new User(); user.setAge(5); //user.setName("李白"); session.save(user); mySessionFactory.commit(); mySessionFactory.close(); } }
這裡的MySessionFactory是前面部落格寫的工具類,參考前面的部落格。
執行後將在資料庫中生成一個tb_user表,以及儲存一條資料,檢視控制檯可以看到列印的sql語句
Hibernate:
insert
into
tb_user
(age, name)
values
(?, ?)
儘管上面只對age進行賦值,但是hibernate還是生成了這條對age與name列的插入語句,為了提高效能,只對我們賦值的屬性進行插入,我們可以將DynamicInsert註解括號內的false改為true或者將false去掉(預設括號內值為true)
再次執行,檢視控制檯列印的sql語句,滿足需求
Hibernate:
insert
into
tb_user
(age)
values
(?)
主鍵生成策略@GeneratedValue(strategy = GenerationType)
資料表中主鍵的生成策略有很多種方式,這裡測試一下其中的4種
第一種型別IDENTITY
這是MySQL和SqlServer的主鍵生成方式,在主鍵屬性上宣告此主鍵生成型別,每次插入資料時主鍵會自動遞增,而無需對主鍵賦值
示例程式碼:
User.class
@Entity(name="tb_user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
以及一個測試類,PrimaryKey.class
public class PrimaryKey {
public static void main(String[] args) {
// TODO Auto-generated method stub
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
// user.setId(1);
user.setAge(10);
user.setName("李牧");
session.save(user);
mySessionFactory.commit();
mySessionFactory.close();
}
}
執行後資料表tb_user中插入一條名稱為“李牧”的資料,主鍵為1,如果再次執行會發現插入的下一條資料主鍵自動增長為2
第二種型別SEQUENCE
@GeneratedValue(strategy = GenerationType.SEQUENCE)這個註解是對於Oracle資料庫的,因為本機沒有安裝Oracle,所以可以自行測試
第三種類型AUTO
@GeneratedValue(strategy = GenerationType.AUTO)
AUTO型別能夠自動識別你所使用的資料庫型別,再根據型別來生成主鍵策略(如使用mysql時生成mysql的主鍵自增策略,使用Oracle時使用Oracle的主鍵策略),將主鍵生成策略改為此型別,執行後生成的表插入資料同樣會自動插入主鍵
第四種類型TABLE
@GeneratedValue(strategy = GenerationType.TABLE)
把剛剛建立的tb_user表刪除,將主鍵生成策略使用TABLE型別,再次執行測試,可以看到資料庫裡多了兩張表,一張是我們建立的tb_user,一張叫做hibernate_sequences,用來儲存下一條主鍵的資訊
在執行完畢後控制檯列印了這些sql語句
Hibernate:
select
sequence_next_hi_value
from
hibernate_sequences
where
sequence_name = 'tb_user' for update
Hibernate:
insert
into
hibernate_sequences
(sequence_name, sequence_next_hi_value)
values
('tb_user', ?)
Hibernate:
update
hibernate_sequences
set
sequence_next_hi_value = ?
where
sequence_next_hi_value = ?
and sequence_name = 'tb_user'
Hibernate:
insert
into
tb_user
(age, name, id)
values
(?, ?, ?)
從SQL語句中瞭解到,hibernater在插入資料時,會先查詢出存放下一個主鍵的這張表(hibernate_sequences)中的sequence_next_hi_value列的值,然後再插入資料,並更新hibernate_sequences表
檢視資料表,多了一條name為“李牧”的資料,Id為1
再次執行發現新插入的資料id變成了32768,這是因為Hibernate會查出hibernate_sequences表中下一個主鍵的值後,用它乘2的15次方作為主鍵,如果再插入一條資料的話,那麼主鍵應該會是65536(對於這個主鍵的生成規則,其實並不需要了解...不建議使用TABLE作為主鍵生成策略,因為在插入資料時要做這一系列操作肯定對效能會有影響)
聯合主鍵
如果一張表需要多個主鍵的話,可以為其他屬性也加上@Id註解,同時還需要實現序列化物件介面(hibernate需要將多個主鍵進行序列化來拼接主鍵)
示例程式碼:
@Entity(name="tb_user")
public class User implements Serializable{
@Id
private int id;
@Id
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
列註解@Column
@Column(name="myname",length=99,unique=true)
private String name;
列註解有多個屬性,這裡name表示將該列的名字改為myname,length表示長度為99,unique表示唯一性約束為true
除此之外,還有其他屬性
如:
-precision:有效位數
-insertable:是否允許插入
-updatable:是否執行修改
-nullable:非空約束
-scale:小數點的位數
-columnDefinition:列的定義
columnDefinition示例:
@Column(name="myname",columnDefinition="int(66) not null")
private String name;
嵌入式主鍵
嵌入式主鍵即以一個實體類作為主鍵,這個類中的屬性作為表的列
例如下面的程式碼(需要實現序列化介面),其中有id和name兩個屬性
public class IdAndName implements Serializable{
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
再將這個類作為主鍵,使用@EmbeddedId這個註解,這樣id和name就是聯合主鍵了
示例程式碼:
@Entity(name="tb_user")
public class User{
@EmbeddedId
private IdAndName idAndName;
public IdAndName getIdAndName() {
return idAndName;
}
public void setIdAndName(IdAndName idAndName) {
this.idAndName = idAndName;
}
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
測試類程式碼:
public class PrimaryKey {
public static void main(String[] args) {
// TODO Auto-generated method stub
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
IdAndName idAndName = new IdAndName();
idAndName.setId(1);
idAndName.setName("ts");
user.setIdAndName(idAndName);
user.setAge(10);
session.save(user);
mySessionFactory.commit();
mySessionFactory.close();
}
}
執行後檢視資料庫可以看到資料表中有id、name、age三個列,這是因為Hibernate將IdAndName中的屬性析出來作為資料列了
如果想要對IdAndName類中的屬性進行別名或者使用其他限制時,除了可以直接在IdAndName類中對屬性進行註解外,還可以使用@AttributeOverrides註解進行復合屬性的註解
@AttributeOverrides屬性重寫
在上一個註解的基礎上,使用@AttributeOverrides進行屬性的重寫,程式碼如下:
將IdAndName類中的id屬性進行列別名,別名為"my_id",還可以指定長度等其他屬性,其他屬性參考上面的列註解
將IdAndName類中的name屬性進行列別名,別名為"my_name",長度為99
@Entity(name="tb_user")
@DynamicUpdate(false)
public class User{
@Id
@Embedded
@AttributeOverrides({@AttributeOverride(name="id",[email protected](name="my_id",length=11))
,@AttributeOverride(name="name",[email protected](name="my_name",length=99))})
private IdAndName idAndName;
private int age;
public IdAndName getIdAndName() {
return idAndName;
}
public void setIdAndName(IdAndName idAndName) {
this.idAndName = idAndName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
測試程式碼:
public class PrimaryKey {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setAge(10);
IdAndName idAndName = new IdAndName();
idAndName.setId(1);
idAndName.setName("王翦");
user.setIdAndName(idAndName);
session.save(user);
mySessionFactory.commit();
mySessionFactory.close();
}
}
大的二進位制或文字註解@Lob
這個註解用來儲存一些大的二進位制或文字資料,例如圖片(一般web專案推薦只儲存圖片的路徑名,通過路徑名來找到圖片,而不是直接儲存圖片)
示例程式碼:
@Entity(name="tb_user")
@DynamicUpdate(false)
public class User{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
private int age;
@Lob
private byte[] image;
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
其中Image屬性用來儲存圖片
測試程式碼:
public class PrimaryKey {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setId(2);
user.setAge(10);
user.setName("李牧");
InputStream is = PrimaryKey.class.getResourceAsStream("a2.png");
byte[] image = new byte[is.available()];
is.read(image);
is.close();
user.setImage(image);
session.save(user);
mySessionFactory.commit();
mySessionFactory.close();
}
}
取測試類PrimaryKey同目錄下的a2.png圖片寫到位元組數組裡,呼叫save方法儲存,儲存成功後可以將資料表中的這一列資料儲存出來,儲存為png格式,開啟圖片正常顯示
日期格式註解@Temporal
-TemporalType.DATE:yyyy-MM-dd 顯示日期
-TemporalType.TIME:HH:mm:ss 只顯示時間
-TemporalType.TIMESTAMP:yyyy-MM-dd HH:mm:ss 全日期顯示
示例程式碼:
@Entity(name="tb_user")
public class User{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
private int age;
@Temporal(TemporalType.TIMESTAMP)
private Date date;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
測試類程式碼:
public class PrimaryKey {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
MySessionFactory mySessionFactory = new MySessionFactory();
Session session = mySessionFactory.getSession();
User user = new User();
user.setAge(10);
user.setName("李牧");
user.setDate(new Date());
session.save(user);
mySessionFactory.commit();
mySessionFactory.close();
}
}
完成