hibernate主键生成策略
来源:互联网 发布:c语言经典编程案例 编辑:程序博客网 时间:2024/03/29 13:21
使用mySql生成联合主键需要注意的地方:
生成联合主键的各个列不可以为空,首先要设置好,也不可以有一个为主键,
因为主键只有一个,如果联合主键其中的一个为主键的话,那么就没有必要再去
生成联合主键了.
使用联合主键的时候要注意:联合主键需要实现serializable接口,实现了这个接口后还最好要重写
equals和toString()方法,这两个方法如果不写的话,刚开始是看不到错误的,但是等你开始真正的运行的时候就会报错了.
应该是任何的数据库的主键生成策略都是一样的.
在改造系统自动生成的联合主键的过程中注意修改好:
比如系统自动生成的是:
<composite-id name="id" class="com.dada.foreign.TwoId">
<key-property name="id" type="java.lang.Integer">
<column name="id" />
</key-property>
<key-property name="name" type="java.lang.String">
<column name="name" length="20" />
</key-property>
</composite-id>
如果想自己改造一下这个实体,让它只是需要一个类就可以,这种情况下
要这样来修改:
<composite-id>
<key-property name="id" type="java.lang.Integer">
<column name="id" />
</key-property>
<key-property name="name" type="java.lang.String">
<column name="name" length="20" />
</key-property>
</composite-id>
就是只是需要把composite标签里面的属性给删除掉就好了,然后再修改
系统自动生成的实体类,这个时候需要把包含在那个生成联合逐渐的实体
类中的属性都放入到生成实体的主体类当中,而且需要提供每个属性的
get和set方法,之后再添加一个只是包含了联合主键的构造方法就可以了.
然后再把没有用的属性都给删除掉,在对实体进行操作的时候,记住要首先
使用构造方法生成主键,然后再执行其他的操作.
联合主键是需要生成这个主键的hashCode和equals方法的
public class TwoId implements java.io.Serializable {
// Fields
private Integer id;
private String name;
getter and setters
public boolean equals(Object other) {
if ((this == other))
return true;
if ((other == null))
return false;
if (!(other instanceof TwoId))
return false;
TwoId castOther = (TwoId) other;
return ((this.getId() == castOther.getId()) || (this.getId() != null
&& castOther.getId() != null && this.getId().equals(
castOther.getId())))
&& ((this.getName() == castOther.getName()) || (this.getName() != null
&& castOther.getName() != null && this.getName()
.equals(castOther.getName())));
}
public int hashCode() {
int result = 17;
result = 37 * result + (getId() == null ? 0 : this.getId().hashCode());
result = 37 * result
+ (getName() == null ? 0 : this.getName().hashCode());
return result;
}
}
--------------------------------------------------------------------------------------------------
使用annotation生成联合主键
1.把提供主键的类设置为@Embeddable表明这个类可以作为一个嵌入的类,然后在需要此类的地方进行引用时为这个
组件的引用加上@Id注解就可以了.
2.将组件的属性设置为Embeddable,就是说这个组件类本身是不带有注解的,但是对它进行引用的实体就需要在使用
它的时候对他加上Embedded这个注解
3.将实体类设置为IdClass,然后把实体中所有属于主键的属性给标注为@Id就行了.
三种方式的使用情况,第一种的使用情况是非常少的,因为第二种就可以直接的比它少了一步,第二种方式是最常用的,
第三种也有用的,但是用的少,为什么呢?
这个是因为如果使用了联合主键之后,自己总还是需要从数据库中去读取东西的,这个时候呢就有必要把它给读出来,
怎么读呢?使用面向对象的方法就需要提供主键的对象,这个时候就需要使用到它了.
--------------------------------------------------------------------------------------------------
一对一单相外键关联
这种情况就会导致的是在此表中会多生成一个字段那就是wife_id是作为这个表的一个外键.
如果要指定生成的外键字段就需要这样设置:
@OneToOne
@JoinColumn(name="wifeId")
private Wife1 wife;
@Entity
public class Husband1 {
@Id
@GeneratedValue
private Integer id;
private String name;
@OneToOne
private Wife1 wife;
public Wife1 getWife() {
return wife;
}
}
当然双向关联就容易了,只需要在wife实体中也持有一个对Husband的引用就可以了.
但是又这样的一个需求,就是,需要设置双向的关联,但是实际上只需要在自己或者对方
设置一个引用就可以了,就是说,两个表虽然是双向的关联,但是并不需要设置两个外键
这样设置是多余的,这种情况下应该怎么弄呢?
这个时候应该在不需要设置外键的一方中设置好mappedBy就好了,如下
@OneToOne(mappedBy="wife")
private Husband1 husband1;
其中mappedBy的意思是这个外键关系是由对方来主导的,使用的是对方的wife属性来主导的.
这样设置之后就可以达到使用一个外键而得到双向关联的目的了.
在xml中这种双向关联,只生成一个外键的设置方式是:
<one-to-one name="wife" property-ref="student">
同样的,这里的student也是对方实体里面的一个引用.
只要有双向关联必然需要设置mapped
如果是设置为一对一的主键关联的话,就把
@JoinColumn(name="wifeId")
修改为
@PrimaryKeyJoinColumn
--------------------------------------------------------------------------------------------------
多对多单向关联
单向关联只需要在一方设置好关联关系就好了,另外的一方不要设置的.
@Entity
public class Student {
@Id
private int id;
private String name;
@ManyToMany
private Set<Teacher> teachers = new HashSet<Teacher>();
}
注意在这个地方设置@ManyToMany的mappedBy属性是没有用的,因为
它根本不需要生成外键,而是生成一个中间表,这个时候如果想要指定
生成的中间表的名称和中间表中的字段的名字的话,就需要设置:
@JoinTable(
name="t_s",//指明中间表的名字
joinColumns={@JoinColumn(name="stu_id")},//指明本实体
//的主键在中间表中的外键的名字
inverseJoinColumns={@JoinColumn(name="tea_id")}
//指明另外一方实体在中间表中的外键的名字.
)
在xml配置中中间表的名称是在类的hbm的<set>标签中配置的.
---------------------------------------------------------------------------------------------------------------------------------------------------
Hibernate更新指定的字段
1需求,有一个表里面记录的是学生的姓名,学号和他的爱好论文这个时候如果这个表需要更新,
那么在hibernate中默认的更新是把所有的字段全部都更新一遍,因此就会出现在更新一个人的
爱好的时候却需要把论文也更新的情况,这种情况很显然很耗资源也没有必要,这个时候可以这样
配置
在对应的论文字段上加上注解@Colum(updatable=false);
或者在对应的xml的配置文件中配置一下<property>标签的update属性也是可以的.
但是上面的这两种方式都太不灵活了,因此需要使用第三种方式就是在xml中配置
<hibernate-mapping>
<class catalog="shopping" name="com.dada.entities.Notebook" table="notebook" dynamic-update="true">
这个时候呢就是dynamic-update="true"这句话起作用了,它可以动态的去修改.
不过这种动态的改变有个限制就是只能够在xml文件中去配置,而不可以在annotation中去配置,所以
如果需要使用动态的改变的话,就使用xml去配置这个文件就好了.
当然如果不想使用这种动态的配置的话,也可以使用类似于sql的hql语句来实现对特定的一个字段进行修改.
但是即便是动态的修改它还是有条件的,条件就是动态修改的条件,如何才能知道哪些属性改变了呢?
肯定是拿现在的属性跟数据库的属性进行了比较了,那怎么跟数据库里面的数据进行比较呢?
那肯定是把数据库里面的东西给load进入内存里面了,这样才能对修改后的内容跟修改之前的内容进行比较
所以就是执行动态代理的条件就是,被执行动态代理的对象是持久化的也就是被load或者get进入内存的.
但是有的时候会出现这种需求就是跨session去修改数据库,这个时候应该使用的是merge()它的意思是合并
这个在hibernate中实现的细节是:先从数据库中去load这个对象,之后再把要合并的东西跟数据库里面的进行
对比,然后再去修改到数据库里面.
clear()清空缓存内容;
flush:强制缓存内容与数据库同步;
比如
p.setName("a");
p.setName("aa");
session.save(p);
这个时候hibernate中会生成一条语句这个时候只是执行最后一次的更新.
如果使用的是
p.setName("a");
session.flush();
p.setName("aa");
session.save(p);
session.flush();
这句话会产生这样的效果:
1.hibernate会向数据库发送两条语句,一条是执行第一个更改
2.执行第二次更改
如果把session.flush();换成为session.clear();
那么结果就是内存被清空,然后呢持久化的对象都没有了这个时候,当然就谈不上是更改了.
当然在执行commit();方法的时候,系统就会默认的实现flush();这个方法的.
- hibernate主键生成策略
- Hibernate 主键生成策略
- Hibernate 主键生成策略
- hibernate 主键生成策略
- Hibernate 主键生成策略
- Hibernate 主键生成策略
- Hibernate 主键生成策略
- hibernate主键生成策略
- hibernate主键生成策略
- Hibernate主键生成策略
- hibernate主键生成策略
- hibernate主键生成策略
- Hibernate主键生成策略
- Hibernate 主键生成策略
- Hibernate 主键生成策略
- hibernate主键生成策略
- hibernate主键生成策略
- HIBERNATE主键生成策略
- 动态代理
- 如何为嵌入式开发建立交叉编译环境
- 项目总结
- Win7不生成Thumbs.db文件的方法
- MySql在Win7中的导入与导出
- hibernate主键生成策略
- hibernate Annotation用法
- Bit-map(1)
- 使用外键的一对多的配置:
- 编写一个脚本
- 感谢CSND,感谢在技术,人生道路给予我帮助的人
- Java Hotspot VM [顶]
- 这是个装逼的世界
- 位图bitmap算法2