• Jpa配置一对多关系


    在网上查了很多关于jpa的一对多表关联的操作,踩了很多坑,今天终于解决了

    下面上一下我自己的代码,记录一下

    老师和学生(一对多关系)

    首先搭建环境,添加依赖包

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.lyf</groupId>
        <artifactId>one-to-more</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.3.RELEASE</version>
        </parent>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.47</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.22</version>
            </dependency>
        </dependencies>
    </project>

    编写数据库配置文件

    spring.datasource.url=jdbc:mysql://localhost:3306/jpa?serverTimezone=UTC
    spring.datasource.username=root
    spring.datasource.password=08186912
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.jpa.hibernate.ddl-auto=update
    spring.jpa.show-sql=true
    spring.jpa.database=mysql

    实体类

    package com.lyf.pojo;
    
    import lombok.Data;
    
    import javax.persistence.*;
    
    /**
     * @Date:2019-04-12
     * @Description:com.lyf.pojo
     * @version:1.0
     */
    @Data
    @Entity
    @Table(name = "tb_student")
    public class Student {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "s_id")
        private Long sId;
        @Column(name = "s_name")
        private String sName;
    
        /**
         * 多个学生对应一个老师
         * 注解形式配置多对一
         *  1,配置表关系
         *  2,配置外键
         */
        @ManyToOne(targetEntity = Teacher.class)
        @JoinColumn(name = "s_t_id",referencedColumnName = "t_id")
        private Teacher teacher;
    }

    package com.lyf.pojo;

    import lombok.Data;

    import javax.persistence.*;
    import java.util.HashSet;
    import java.util.Set;

    /**
    * @Date:2019-04-12
    * @Description:教师和学生是一对多
    */
    @Data
    @Entity
    @Table(name = "tb_teacher")
    public class Teacher {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "t_id")
    private Long tId;
    @Column(name = "t_name")
    private String tName;
    //配置老师和学生一对多
    /**
    * 注解配置多表关系
    * 1,声名关系
    * 2,配置外键,或者中间表
    * OneToMany配置一对多
    * targetEntity设置对应的实体类的类型
    * JoinColumn 配置外键
    * name:外键的名称,
    * referencedColumnName参照的主表的主键字段名称
    */
    @OneToMany(targetEntity = Student.class)
    @JoinColumn(name = "s_t_id",referencedColumnName = "t_id")
    private Set<Student> students = new HashSet<>();
    }
     

    springboot启动类(引导类)

    package com.lyf;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * @Date:2019-04-12
     * @Description:com.lyf
     * @version:1.0
     */
    @SpringBootApplication
    public class App {
        public static void main(String[] args) {
            SpringApplication.run(App.class,args);
        }
    }

    启动引导类,查看数据库会发现表生成成功

    dao层代码就不上了,继承JpaRepository就行了

    接下来我们进行保存操作

    package com.lyf;
    
    import com.lyf.dao.StudentDao;
    import com.lyf.dao.TeacherDao;
    import com.lyf.pojo.Student;
    import com.lyf.pojo.Teacher;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    /**
     * @Date:2019-04-12
     * @Description:com.lyf
     * @version:1.0
     */
    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class OneToMoreTest {
    
        @Autowired
        private TeacherDao teacherDao;
        @Autowired
        private StudentDao studentDao;
        @Test
        public void addTest(){
            Student student = new Student();
            student.setSName("老篮孩i");
            Teacher teacher = new Teacher();
            teacher.setTName("刘老师");
            //关联学生和老师,添加学生信息时,还需添加外键的值
            student.setTeacher(teacher);
    
    
            studentDao.save(student);
            teacherDao.save(teacher);
        }
    }

    结果报错了,发现我是先保存的学生信息,再保存的老师信息,此时数据库中并没有老师的信息,给学生关联老师信息肯定是有问题的

    报错信息

    org.springframework.dao.InvalidDataAccessApiUsageException: 
      org.hibernate.TransientPropertyValueException:
         object references an unsaved transient instance - save the transient instance before flushing : com.lyf.pojo.Student.teacher -> com.lyf.pojo.Teacher;
          nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException:
            object references an unsaved transient instance - save the transient instance before flushing :
              com.lyf.pojo.Student.teacher -> com.lyf.pojo.Teacher

     学生表记录插入了,老师表是空的

    改成

    package com.lyf;
    
    import com.lyf.dao.StudentDao;
    import com.lyf.dao.TeacherDao;
    import com.lyf.pojo.Student;
    import com.lyf.pojo.Teacher;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    /**
     * @Date:2019-04-12
     * @Description:com.lyf
     * @version:1.0
     */
    @SpringBootTest
    @RunWith(SpringRunner.class)
    public class OneToMoreTest {
    
        @Autowired
        private TeacherDao teacherDao;
        @Autowired
        private StudentDao studentDao;
        @Test
        public void addTest(){
            Student student = new Student();
            student.setSName("老篮孩i");
            Teacher teacher = new Teacher();
            teacher.setTName("刘老师");
            //关联学生和老师,添加学生信息时,还需添加外键的值
            student.setTeacher(teacher);
    
            //要先保存主表信息
            teacherDao.save(teacher);
            studentDao.save(student);
        }
    }

     控制台信息,很显然成功了

    Hibernate: alter table tb_student add constraint FKsojy7bicq68v21slcq9mtwtou foreign key (s_t_id) references tb_teacher (t_id)
    2019-04-12 23:29:42.036  INFO 10980 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
    2019-04-12 23:29:42.748  INFO 10980 --- [           main] com.lyf.OneToMoreTest                    : Started OneToMoreTest in 7.77 seconds (JVM running for 9.806)
    Hibernate: insert into tb_teacher (t_name) values (?)
    Hibernate: insert into tb_student (s_name, s_t_id) values (?, ?)

    查看数据库也没有问题

    同样我们通过Teacher表也能完成关联操作,保存也是没有问题的

    @Test
        public void addTest1(){
            Student student = new Student();
            student.setSName("老篮孩i1");
            Teacher teacher = new Teacher();
            teacher.setTName("刘老师1");
    
            //通过主表来添加关联
            teacher.getStudents().add(student);
            studentDao.save(student);
            teacherDao.save(teacher);
        }

     控制打印信息

    Hibernate: insert into tb_student (s_name, s_t_id) values (?, ?)
    Hibernate: insert into tb_teacher (t_name) values (?)
    Hibernate: update tb_student set s_t_id=? where s_id=?

    学生类和老师类都添加类外键的配置,都具备外键的维护,那么我们这里可以通过学生找到老师,也能通过老师找到学生,这是一种双向关系

    如果只配置一方,那就是单向的关系,只能通过指定的一方找到另一方

  • 相关阅读:
    leetcode 198. House Robber
    leetcode 35. Search Insert Position
    一文读懂机器学习,大数据/自然语言处理/算法全有了……
    成都Uber优步司机奖励政策(1月30日)
    北京Uber优步司机奖励政策(1月30日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(1月30日)
    成都Uber优步司机奖励政策(1月29日)
    北京Uber优步司机奖励政策(1月29日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(1月29日)
    成都Uber优步司机奖励政策(1月28日)
  • 原文地址:https://www.cnblogs.com/a-small-lyf/p/10699326.html
Copyright © 2020-2023  润新知