今天这篇博客将会主要学习hibernate关于实体类和表格中的映射详细学习。首先看下”常用主键的生成策略”
hibernate常用主键生成策略
在hibernate中,每个主键必须定义相应的主键生成策略,它用来为持久化类实例生成唯一的标识。
1.assigned
在hibernate中,如果不想使用hibernate的主键生成策略,那么此时就需要自己指定主键,此时的主键生成策略,就需要使用assigned。
在使用assigned的时候,必须手动指定id,比如我连续两次执行如下代码:
transaction = session.beginTransaction();
UserInfo info = new UserInfo();
info.setUserName("aa");
info.setUserPass("vvv");
session.save(info);
transaction.commit();
当第一次执行的时候,此时主键id,默认是0,而第二次执行,由于我们没有自己指定id,所以还是会使用默认值的,所以hibernate会抛出如下异常:
2.increment
这里使用hibernate的主键自增的生成策略,主要为long,short或者int类型生成唯一标识,只有在没有其他进程给同一张表中插入数据才能使用,在集群下不要使用,不依赖数据库。比如这次给userinfo的主键使用increment。
<id name="userId" column="uid">
<!-- 主键的生成策略:native(主键自增),assigned(指派) -->
<generator class="increment"></generator>
</id>
此时我在多次执行上面的插入方法,就不会抛出异常,因为此时是主键自增的。在指定为increment的时候,当插入的时,hibernate首先在数据库当中查询最大的id值,然后对该id加一,再次插入。
3.native和identity
代表主键自增的意思,根据数据库不同,hibernate自动选择不同的实现方式。
4.hilo
使用一个高/低位算法高效生成long,short或者int类型的标识符,给定一个表和字段(默认分别是hibernate_unique_key和next_hi)作为高位值的来源,高/低位算法生成的标识符,只在一个特定的数据库当中是唯一的。
<id name="userId">
<generator class="hilo"></generator>
</id>
这里我们制定id的生成策略是hilo,此时两次执行插入操作:
transaction = session.beginTransaction();
UserInfo info = new UserInfo();
info.setUserName("aa");
info.setUserPass("vvv");
session.save(info);
transaction.commit();
此时,hibernate为我们额外生成了一张表:hibernate_unique_key在该表中一个字段next_hi
可以看到,此时hibernate自动为我们生成主键
上面说了,默认维护主键的表示hibernate_unique_key,不过我们也可以自己指定。
<id name="userId">
<generator class="hilo">
<param name="table">testprimary</param>
<param name="column">testcolumn</param>
</generator>
</id>
5.uuid
uuid表示为string类型的属性生成主键,并且生成的主键也是一个唯一的字符串。比如我将userinfo的实体类的id更改为string类型。主键生成策略指定为uuid
<id name="userId">
<generator class="uuid">
</generator>
</id>
此时多次执行插入操作:
6.联合主键生成策略
如果使用联合主键生成策略,就不能像之前那样使用简单的两个字段来代替了,此时必须使用一个实现Serializable接口的实体类。
package com.mydb.entity;
import java.io.Serializable;
public class ComposeKey implements Serializable {
private int userId;
private String userAddress;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((userAddress == null) ? 0 : userAddress.hashCode());
result = prime * result + userId;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ComposeKey other = (ComposeKey) obj;
if (userAddress == null) {
if (other.userAddress != null)
return false;
} else if (!userAddress.equals(other.userAddress))
return false;
if (userId != other.userId)
return false;
return true;
}
}
可以看到这里,我使用userId和userAddress这两个字段来保证联合主键,主要ComposeKey必须实现hashCode和equals方法,因为hibernate是使用这两个方法来比较两个对象是否相等,从而保证联合主键的唯一性。
此时UserInfo类内容如下:
package com.mydb.entity;
import java.io.Serializable;
public class UserInfo implements Serializable {
private ComposeKey composeKey;
private String userName;
private String userPass;
public ComposeKey getComposeKey() {
return composeKey;
}
public void setComposeKey(ComposeKey composeKey) {
this.composeKey = composeKey;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPass() {
return userPass;
}
public void setUserPass(String userPass) {
this.userPass = userPass;
}
}
接下来就是配置联合主键了。UserInfo.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- name="全类名" table="表名" -->
<class name="com.mydb.entity.UserInfo" table="userinfo" lazy="false">
<composite-id name="composeKey" class="com.mydb.entity.ComposeKey">
<key-property name="userId"></key-property>
<key-property name="userAddress"></key-property>
</composite-id>
<property name="userName" column="uname"></property>
<property name="userPass" column="upass"></property>
</class>
</hibernate-mapping>
此时,执行插入操作,由于使用了联合主键,相当于我们自己指定了主键,需要显示的set来设置主键:
transaction = session.beginTransaction();
UserInfo info = new UserInfo();
info.setComposeKey(new ComposeKey(1,"china"));
info.setUserName("aa");
info.setUserPass("vvv");
session.save(info);
transaction.commit();
可以看到这个时候userId和userAddress这两个属性,联合用来作为userInfo表中的主键的。此时如果我在插入一条id是info.setComposeKey(new ComposeKey(1,”china”));这样的数据,hibernate就会为我们抛出如下异常:
属性的映射
对于属性的映射,常见的属性如下:
1.name:对应类的属性名称
2.type:指定属性的类型,一般情况下可以不使用,有hibernate自动匹配
3.length:指定长度
4.column:指定属性所对应的数据库字段的名称,如果不指定,就是属性的名称
5.not-null:是否非空
6.unique:是否唯一
7.update:是否在发出update语句的时候,包含本属性
当需要存入一个很长的文本,比如一本小说的时候,需要指定type类型为”text”,这种类型只受硬盘大小的限制。
好了,关于hibernate的一对一的映射学习,就到这里了,下一篇博客将会学习hibernate关联映射。希望大家能够喜欢。