一对一映射
就像人和身份证之间就是一个典型的一对一映射关系,下边介绍一对一映射的一个小例子:
一对一映射项目结构
application.properties
# 连接数据库的四大参数
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://127.0.0.1:5432/jpa
spring.datasource.username=postgres
spring.datasource.password=123456
# jpa相关配置
# 开发阶段可以 设置为true,开启逆向工程,在实际上线运行阶段,实体类和底层的数据库表都是已经存在,应该设置成false
# 数据库和java映射 正向工程 逆向工程
# 逆向工程: 存在数据库的表,然后数据库表可以生成对应实体类
# 正向工程: 先是存在实体类,然后根据实体类,生成底层的表
spring.jpa.generate-ddl=true
# create: 设置为create,每次运行程序都会将原来的数据表删除,然后重新创建一个表
# create-drop: 每次床架你个数据表,数据表使用完毕之后,将数据表再次删除
# none: 将功能不生效
# update: 如果你设定的实体类发生了改变,数据表会更新
# 如果数据库当中有数据表,就使用原来的表,没有数据表,就会创建一个数据表。也是在开发当中使用
# validate: 实体类和数据表进行校验,如果属性或个数不一致,就会出异常
spring.jpa.hibernate.ddl-auto=update
# 操作实体对象的时候,会为我们生成sql语句: false 不生成sql语句
spring.jpa.show-sql=true
# 指定数据库的类型
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL10Dialect
# 上线运行时只有spring.jpa.database-platform是真实有效的
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>jpa_onetoone</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>jpa_onetoone</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
dao
public interface BoyDao extends JpaRepository<Boy,Integer>{
}
public interface GirlDao extends JpaRepository<Girl,Integer> {
}
entity
@Getter
@Setter
@Entity(name = "t_boy")
public class Boy {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int bid;
@Column
private String bname;
@OneToOne(cascade = CascadeType.ALL)
//添加一个唯一值约束,否则就是一对多关系
@JoinColumn(name = "gid",unique = true)
private Girl girl;
}
@Getter
@Setter
@Entity(name = "t_girl")
public class Girl {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int gid;
@Column
private String gname;
@OneToOne(mappedBy = "girl")
private Boy boy;
}
测试类
@SpringBootTest
class JpaOnetooneApplicationTests {
@Autowired
private GirlDao girlDao;
@Autowired
private BoyDao boyDao;
@Test
void contextLoads() {
System.out.println("初始化数据库表。。。。。");
}
/**
* 保存girl信息
*/
@Test
public void addGirl(){
//创建girl信息
Girl girl = new Girl();
girl.setGname("小花");
girlDao.save(girl);
}
/**
* 保存boy信息
* 添加boy信息并且维护外键
*/
@Test
public void addBoy(){
Boy boy = new Boy();
boy.setBname("小李");
Girl girl = girlDao.getOne(30);
//创建关联关系
boy.setGirl(girl);
boyDao.save(boy);
}
/**
* 保存boy信息,级联保存girl信息
* boy
* girl
* 直接保存:异常信息 TransientPropertyValueException:boy持久态对象,关联了一个瞬时态对象
*
* 解决方案: 级联操作:保存boy
*/
@Test
public void addBoyAndGirl(){
Boy boy = new Boy();
boy.setBname("小王");
Girl girl = new Girl();
girl.setGname("小八");
//创建关联关系
boy.setGirl(girl);
boyDao.save(boy);
}
//更新操作
@Test
public void UpdateGirl(){
Girl girl = new Girl();
girl.setGname("小雨");
girl.setGid(35);
//更新
girlDao.save(girl);
}
//更新操作
@Test
public void UpdateBoy(){
//需求:修改boy信息重新分配girl
Boy boy = new Boy();
boy.setBid(34);
boy.setBname("小王");
Girl girl = girlDao.getOne(36);
//设置关联关系
boy.setGirl(girl);
//更新
boyDao.save(boy);
}
/**
* 查询操作
* 查询girl信息
*/
@Test
public void findGirl(){
//girl.getOne() 该方法高版本中被findById替代了
Optional<Girl> girl1 = girlDao.findById(37);
Girl girl = girl1.get();
System.out.println(girl.getGid()+","+girl.getGname());
}
/**
* 查询男孩信息:关联查询女孩信息
* 结论:查询boy信息的时候 发送的语句是左外连接查询,将boy信息关联的girl信息一并查询
*/
@Test
public void findBoy(){
//girl.getOne() 该方法高版本中被findById替代了
Optional<Boy> boy1 = boyDao.findById(34);
Boy boy = boy1.get();
System.out.println(boy.getBid()+","+boy.getBname()+","+boy.getGirl().getGid()+","+boy.getGirl().getGname());
}
/**
* 删除操作
* 删除girl信息
*/
@Test
public void delGirl(){
girlDao.deleteById(37);
}
/**
* 删除girl信息,如果被引用过,则不会被删除
* del删除原理:先查询后删除
*/
@Test
public void delGirl2(){
girlDao.deleteById(30);
}
/**
* 删除boy信息
*/
@Test
public void delBoy(){
boyDao.deleteById(32);
}
}