这是一个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类为自定义的工具类,参考前面的博文
Hibernate持久层框架使用【二】数据添加与修改
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
(?)
数据表中主键的生成策略有很多种方式,这里测试一下其中的4种
这是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
@GeneratedValue(strategy = GenerationType.SEQUENCE)这个注解是对于Oracle数据库的,因为本机没有安装Oracle,所以可以自行测试
@GeneratedValue(strategy = GenerationType.AUTO)
AUTO类型能够自动识别你所使用的数据库类型,再根据类型来生成主键策略(如使用mysql时生成mysql的主键自增策略,使用Oracle时使用Oracle的主键策略),将主键生成策略改为此类型,运行后生成的表插入数据同样会自动插入主键
@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(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进行属性的重写,代码如下:
将IdAndName类中的id属性进行列别名,别名为"my_id",还可以指定长度等其他属性,其他属性参考上面的列注解
将IdAndName类中的name属性进行列别名,别名为"my_name",长度为99
@Entity(name="tb_user")
@DynamicUpdate(false)
public class User{
@Id
@Embedded
@AttributeOverrides({@AttributeOverride(name="id",column=@Column(name="my_id",length=11))
,@AttributeOverride(name="name",column=@Column(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();
}
}
这个注解用来保存一些大的二进制或文本数据,例如图片(一般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格式,打开图片正常显示
-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();
}
}
完成