关系数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。现实世界中的各种实体以及实体之间的各种联系均用关系模型来表示。关系模型是由埃德加·科德于1970年首先提出的,并配合“科德十二定律”。现如今虽然对此模型有一些批评意见,但它还是数据存储的传统标准。标准数据查询语言SQL就是一种基于关系数据库的语言,这种语言执行对关系数据库中数据的检索和操作。 关系模型由关系数据结构、关系操作集合、关系完整性约束三部分组成。 简单说,关系型数据库是由多张能互相联接的二维行列表格组成的数据库。
one class
package com.example.demo.entity.onetoone;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import lombok.Getter;
import lombok.Setter;
@Entity
@Getter
@Setter
public class One {
@Id
@GeneratedValue
private String id;
private String name;
@OneToOne
private Two two;
}
two class
@Entity
@Getter
@Setter
public class Two {
@Id
@GeneratedValue
private String id;
private String name;
}
默认建表结构
一对一
一对一 如果我们只是单纯的在两个实体类中分别加上@OneToOne注解,会发现两张表都分别引入了对方的主键作为外键。明显的数据冗余,毕竟关系不用双方存储。 利用mappedBy属性,指明关系由哪一方维护。
创建两个实体对象,分别对应一与多的一方。 情况1-只在多的一方在@ManyToOne注解 one方
package com.example.demo.entity.onetomany;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import lombok.Getter;
import lombok.Setter;
@Entity
@Getter
@Setter
public class OneObject {
@Id
@GeneratedValue
private String id;
private String name;
}
many方
package com.example.demo.entity.onetomany;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import lombok.Getter;
import lombok.Setter;
@Entity
@Getter
@Setter
public class OneObject {
@Id
@GeneratedValue
private String id;
private String name;
}
此时我只在多的一方加了一个ManyToOne注解。生成表结构关系如下
只有ManyToOne一个注解 默认是在many_object里面加了一个外键列
只有ManyToOne列属性 情况2-只在one的一方加
只有一个OneToMany注解 默认情况下是生成了一张关系表。用户维护一对多关系。
关系表 至于默认的表名列名,大家可以去看生成规则。不在这篇文章研究范围。 情况3-不想生成关系表,想通过列名维护。 此时使用@JoinColumn属性。 one方
@OneToMany
@JoinColumn(name="obj_id")
private List<ManyObject> manyObject;
many方
@ManyToOne(fetch=FetchType.EAGER,cascade=CascadeType.ALL)
@JoinColumn(name="obj_id")
private OneObject object;
加上@JoinColumn属性表结构
在一对多双方都设置了关联关系后,进行数据存储模拟
@Test
public void contextLoads() {
OneObject object = new OneObject("1");
object.setManyObject(new ArrayList<ManyObject>());
ManyObject manyObject = new ManyObject("ysh");
ManyObject manyObject2 = new ManyObject("ysh2");
object.getManyObject().add(manyObject);
object.getManyObject().add(manyObject2);
mp.save(manyObject);
mp.save(manyObject2);
op.save(object);
}
控制端打印sql如下 除了三条insert数据。还有两条update语句。这个很好理解。先插入多的一方数据,然后在把one对应的一方关联加进去。 想要避免这种多余sql。有两种方式。 方法一:直接把one对应的一方赋值给多的一方。(上面是把多的一方赋值给one的一方)
public void contextLoads() {
OneObject object = new OneObject("1");
object.setManyObject(new ArrayList<ManyObject>());
ManyObject manyObject = new ManyObject("ysh");
ManyObject manyObject2 = new ManyObject("ysh2");
manyObject.setObject(object);
manyObject2.setObject(object);
// object.getManyObject().add(manyObject);
// object.getManyObject().add(manyObject2);
op.save(object);
mp.save(manyObject);
mp.save(manyObject2);
}
控制台日志 可以看到update语句已经没有了。 方法二:利用OneToMany注解里面的mappedBy属性 @OneToMany(mappedBy = "object") // @OneToMany // @JoinColumn(name="obj_id") private List<ManyObject> manyObject; 注意mappedBy不能与@JoinColumn注解连用
利用mappedBy属性后的输出 可以看到也实现了减少两条sql的功能。算是小功能优化。
正常建立两个多对多关系实体 1.多对多实体一
package com.example.demo.entity.manytomany;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
public class Manyone {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToMany
private List<Manytwo> manytwos;
}
多对多实体二
package com.example.demo.entity.manytomany;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Entity
public class Manytwo {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToMany
private List<Manyone> manyones;
}
表结构 很显然的关系表冗余。 利用@ManyToMany(mappedBy="manytwos")的mappedBy属性将关系表改为由一端维护。生成表结构如下:
表结构
public enum CascadeType {
/** Cascade all operations */
ALL,
/** Cascade persist operation */
PERSIST,
/** Cascade merge operation */
MERGE,
/** Cascade remove operation */
REMOVE,
/** Cascade refresh operation */
REFRESH,
/**
* Cascade detach operation
*
* @since Java Persistence 2.0
*
*/
DETACH
}
FetchType.LAZY:懒加载,加载一个实体时,定义懒加载的属性不会马上从数据库中加载。 FetchType.EAGER:急加载,加载一个实体时,定义急加载的属性会立即从数据库中加载。
本文属于基础篇。觉得不错也可以点亮下方小星星。