Jpa的对象关联映射---一对多映射

Jpa对象关联映射关系三种关系

数据库表和表之间的关系、表和表之间都是通过外键维护关系的;
对象和对象之间的关系:

1.	一对多:部门员工 班级学生
2.	多对一:员工部门
3.	多对多:项目员工(拆解成一对多 双向)
4.	一对一:一夫一妻 一个公司 一个注册地址

一对多关系映射–OneToMany

项目结构:
在这里插入图片描述

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是真实有效的

dao

1.ClazzDao —班级

public interface ClazzDao extends JpaRepository<Clazz,Integer> {
}

2.StudentDao —学生

public interface StudentDao extends JpaRepository<Student,Integer> {

}

entity

1.班级信息

@Getter
@Setter
@Entity(name = "t_clazz")
public class Clazz {//new Clazz
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int cid;
    @Column
    private String cname;
    //表示一对多 表示一个班级有多个学生对象
    @OneToMany(mappedBy = "clz",fetch = FetchType.EAGER,cascade = CascadeType.ALL)//mapperBy 创建一和多的映射关系,值是对方的属性名称
    private List<Student> list;
}

2.学生信息

@Getter
@Setter
@ToString
@Entity(name = "t_student")//外键表,子表
public class Student {//new Student
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer sid;
    @Column
    private String sname;
    //表示多对一 多个学生对象属于同一个班级
    @ManyToOne
    @JoinColumn(name="cid")//指定了外键列:外键列没有指定name属性,默认名称clz
    private Clazz clz;

}

测试一对多关系的增删改查接口

@SpringBootTest(classes = JpaOnetomanyApplication.class)
class JpaOnetomanyApplicationTests {
    @Autowired
    ClazzDao clazzDao;
    @Autowired
    StudentDao studentDao;

    @Test
    void contextLoads() {
        System.out.println("初始化数据库表");
    }
    /**
     * 添加操作
     * 添加班级信息
     * 添加学生信息
     */
    @Test
    void testAdd(){
        Clazz clazz = new Clazz();
        clazz.setCname("2班");
        clazzDao.save(clazz);

    }
    @Test
    void testAddStu(){
        //添加学生信息,没有设置学生所属的班级信息
//        Student student = new Student();
//        student.setSname("zhangsan");//student 这个对象没有设置外键时,外键允许为null
//        studentDao.save(student);
        //添加学生信息,设置学生所属的班级信息
        Student student1 = new Student();
        student1.setSname("lisi");
        //创建一个Clazz对象,设置该对象的cid值
        Clazz clazz = new Clazz();
        clazz.setCid(8);//setCid只能来源于t_clazz表中的数据,否则会报错
        student1.setClz(clazz);
        studentDao.save(student1);
    }

    /**
     * 更新班级信息
     */
    @Test
    public void testUpdateClz(){
        //查询出来修改的班级信息
        Clazz clz = new Clazz();
        clz.setCid(15);
        clz.setCname("元宵节1");
        clazzDao.save(clz);
    }
    /**
     * 更新学生信息
     */
    @Test
    public void testUpdateStu(){
        //更新学生信息
        Student student2 = new Student();
        student2.setSid(12);
        //重新分配名称
        student2.setSname("lisisi");
        //准备班级信息
        Clazz clz = new Clazz();
        clz.setCid(8);
        //给student重新分配班级信息
        student2.setClz(clz);
        studentDao.save(student2);
    }
    /**
     * 查询信息
     *  查询班级信息
     *  查询学生信息
     */
    //查询班级信息 关联查询了学生信息:onetomany 是懒加载查询
    @Test
    public void testFindCla(){
        //查询所有的班级信息
        List<Clazz> clazzes = clazzDao.findAll();
        for(Clazz clazz:clazzes){
            /**
             * select * from t_clazz clazz0_
             * 查询班级信息,并没有查询班级中学生的信息
             *
             * 懒加载:查询班级信息并没有发送select语句查询班级当中的学生信息,这样的查询就是懒加载查询
             *          只有当使用到学生信息的时候,才会发送select查询学生信息
             * 立即加载:查询班级信息立即发送select语句查询学生信息
             *  总结:
             *      一般情况下查询一的一方,不需要立即加载。性能降低,建议使用默认值
             *
             *
             */

//            System.out.println(clazz.getCid()+", "+clazz.getCname());
            //查询班级中的学生信息
            /**
             * 查询班级中的学生信息  no Session异常信息
             *  原因:
             *     (1)查询班级信息,当班级信息查询完毕,dao层结束后,session就会关闭
             *     (2)再次调用dao层的方法查询student信息,此时就会没有session对象,所以出现一个no Session异常
             *  解决no Session问题:
             *     (1)设置立即加载 @OneToMany(mappedBy = "clz",fetch = FetchType.EAGER)//mapperBy 创建一和多的映射关系,值是对方的属性名称
             *     (2)延长session的生命周期
             */
            List<Student> students = clazz.getList();
            for(Student student:students){
                System.out.println(student);
            }
            System.out.println(clazz.getCid()+", "+clazz.getCname());
        }

    }

    /**
     * mamyToOne 立即加载
     * 总结: 查询多的一方,立即加载一的一方,立即加载
     */
    @Test
    public void testFindStudents(){
        //查询学生信息
        List<Student> students = studentDao.findAll();
        for(Student student:students){
            //没有使用学生所属的班级信息,但是班级信息也查询了:立即加载
            System.out.println(student.getSid()+", "+student.getSname()+", "+student.getClz().getCid());
        }
    }
    /**
     * 删除操作:
     *  删除班级信息:
     *      主键表主键字段可能引用
     *      也可能没有引用
     *   删除学生信息:
     *
     */
    @Test
    public void deleteClz(){
        //删除班级信息,班级当中没有学生(主键表中主键没有被引用)
//        Clazz clazz = new Clazz();
//        clazz.setCid(15);
//        clazzDao.delete(clazz);
        clazzDao.deleteById(15);
    }

    @Test
    public void deleteClz2(){
        //删除班级信息,班级当中有学生(主键表中主键被引用)
        /**
         * 直接删除班级表删除失败
         *  原因:主键表当中的数据已经被引用了
         *  如何删除?
         *     (1)级联删除:删除班级信息的时候,级联操作学生信息
         *  设置:
         *  cascade = CascadeType.ALL
         *    (2)先断开主外键连接:再去删除主键表当中的数据
         *       step1:断开主外键连接 update
         *       step2:执行一个删除操作
         *       遇到的问题:no Session
         *       解决:添加一个拦截器,延长session的生命周期
         *
         */
        clazzDao.deleteById(13);
    }

    /**
     * 删除外键表(子表)的数据,直接删除就ok
      */
    @Test
    public void deleteStudent(){
        //删除学生信息,不用考虑cid的值,直接删除就ok
//        Student student = new Student();
//        student.setSid(10);
//        studentDao.delete(student);
        //删除没有成功,受到立即加载的影响
        studentDao.deleteById(12);
    }

    /**
     * 添加班级信息同时添加学生信息
     */
    @Test
    public void addClZStudent(){
        //创建班级信息
        Clazz clazz = new Clazz();
        clazz.setCname("java高级就业班");
        //创建学生信息
        Student student = new Student();
        student.setSname("zhangsan");

        Student student1 = new Student();
        student1.setSname("lisi");

        //将学生信息添加到集合
        List<Student> students = new ArrayList<>();
        students.add(student1);
        students.add(student);

        //创建班级学生的关联关系
        clazz.setList(students);

        //创建学生和班级的关联关系 student维护外键关系,多的一方维护外键关系
        student.setClz(clazz);
        student1.setClz(clazz);
        //保存班级信息 没有创建双向关联 数据成功保存,但是外键没有维护,外键的值都是空值
        clazzDao.save(clazz);
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值