对于mybatis中 一对多,多对一情景的理解,以及代码实现

      在学习b站狂神的Mybatis教程中,一对多还有多对一情景中,狂神用现实生活中的老师还有学生的例子做了一个场景,即一个老师对应多个学生,还有多个学生对应一个老师。但是他的数据库表中使用了外键,那么我就想能不能不用外键也可以达成这样的目的呢?

首先我们创建一个名字叫school1的数据库

还有学生表以及老师表,然后给他们插入几条数据

create database school2

`school2`
create table student(
`id` int(20) not null,
`name` varchar(20) not null,
`tid` int(20) not null,
primary key(`id`)

)engine=innodb default charset=utf8

INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('1', '小明', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('2', '小红', '1');
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('3', '小张', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('4', '小李', '1'); 
INSERT INTO `student` (`id`, `name`, `tid`) VALUES ('5', '小王', '1');

create table teacher(
`id` int(20) not null,
`name` varchar(20) not null,
primary key(`id`)

)engine=innodb default charset=utf8

insert into `teacher` (`id`,`name`)values('1','丽丽');

之后我们进行Mybatis的项目结构搭建:

首先是多对一:注意在构建pojo实体类的student类时,要把老师的属性也加入进去

student实体类:

public class Student {
    private int id;
    private String name;
    private int tid;
    private Teacher teacher;

    public Student() {
    }

    public Student(int id, String name, int tid) {
        this.id = id;
        this.name = name;
        this.tid = tid;
    }

    public Teacher getTeacher() {
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
        this.teacher = teacher;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getTid() {
        return tid;
    }

    public void setTid(int tid) {
        this.tid = tid;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", tid=" + tid +
                ", teacher=" + teacher +
                '}';
    }
}

teacher实体类:

public class Teacher {
    private int id;
    private String name;

    public Teacher() {
    }

    public Teacher(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}

之后编写student的接口

public interface StudentMapper {
    List<Student> getStudent();
}

然后对这个接口进行对应的xml文件的配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jin.dao.StudentMapper">
    <select id="getStudent" resultMap="studentTeacher">
        select school1.student.id sid,school1.student.tid stid,school1.student.name sname,school1.teacher.name tname,school1.teacher.id tid
        from school1.student,school1.teacher
        where student.tid=teacher.id
    </select>

    <resultMap id="studentTeacher" type="student">
        <result property="id" column="sid"/>
        <result property="tid" column="stid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="Teacher">
            <result property="id"  column="tid"/>
            <result property="name" column="tname"/>
        </association>
    </resultMap>
</mapper>

以及关键的mybatis的核心配置文件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="db.properties"/>

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

    <!--可以给实体类起别名    -->
    <typeAliases>
        <typeAlias type="com.jin.pojo.Student" alias="student"/>
        <typeAlias type="com.jin.pojo.Teacher" alias="teacher"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper class="com.jin.dao.TeacherMapper"/>
        <mapper class="com.jin.dao.StudentMapper"/>
    </mappers>
</configuration>

通过以上的代码可以看出,对于StudentMapper接口的xml核心配置文件的书写最为关键

我们把查找的对应sql语句写完后要用resaultmap这个属性进行配置,之后我们在进行相应的resaultmap标签的编写

<select id="getStudent" resultMap="studentTeacher">
        select school1.student.id sid,school1.student.tid stid,school1.student.name sname,school1.teacher.name tname,school1.teacher.id tid
        from school1.student,school1.teacher
        where student.tid=teacher.id
    </select>

    <resultMap id="studentTeacher" type="student">
        <result property="id" column="sid"/>
        <result property="tid" column="stid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="Teacher">
            <result property="id"  column="tid"/>
            <result property="name" column="tname"/>
        </association>
    </resultMap>

其中 property属性是映射到你在项目中编写的实体类当中的属性,而后column实行是你在sql语句中写的属性

这里要注意:因为你的 resultmap标签的属性是student那么下面配置的属性中就不能出现有关于teacher的属性

那么我们要怎样来配置teacher的属性呢?

我们就用到了association标签来配置,因为teacher变量的类型是引用类型那么在Javatap中就要填写对应的Teacher类

之后再association标签里面配置你sql中其他出现的属性

然后编写测试类:

测试类要用到的工具类:

public class MybatisUtils {

    static SqlSessionFactory sqlSessionFactory;

    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);
    }
}

测试类:

 @Test
    public void Test2(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> student = mapper.getStudent();
        for (Student student1 : student) {
            System.out.println(student1);
        }
        sqlSession.close();
    }

可以看到运行结果为:

这样多对一的场景就实现了

 

一对多

一对多的实现跟多对一差不多,就是实体类还有接口的xml配置文件有变化

teacher实体类:(在老师的属性中加入了学生集合来实现一对多)

public class Teacher {
    private int id;
    private String name;
    private List<Student> students;

    public Teacher() {
    }

    public Teacher(int id, String name, List<Student> students) {
        this.id = id;
        this.name = name;
        this.students = students;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", students=" + students +
                '}';
    }
}

teachermapper接口:

public interface TeacherMapper {
    Teacher getTeacher(@Param("id") int id);
}

xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jin.dao.TeacherMapper">
    <resultMap id="teacherStudent" type="teacher">
        <result property="id" column="tid"/>
        <result property="name" column="tname"/>
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="tid" column="stid"/>
            <result property="name" column="sname"/>
        </collection>
    </resultMap>
<select id="getTeacher" resultMap="teacherStudent">
    select school1.student.id sid,school1.student.tid stid,school1.student.name sname,school1.teacher.name tname,school1.teacher.id tid
    from school1.student,school1.teacher
    where student.tid=teacher.id and tid=#{id}
</select>

</mapper>

注意我们要配置sql中需要的student属性时就要用collection标签了,然后要用oftype属性来取出集合student中的属性

之后测试类:

public class MyTest {

    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        TeacherMapper mapper = sqlSession.getMapper(TeacherMapper.class);
        Teacher teacher = mapper.getTeacher(1);
        System.out.println(teacher);
        sqlSession.close();
    }

}

最后运行结构:

运行结果:Teacher{id=1, name='丽丽', students=[Student{id=1, name='小明', tid=1}, Student{id=2, name='小红', tid=1}, Student{id=3, name='小芳', tid=1}, Student{id=4, name='小李', tid=1}, Student{id=5, name='小张', tid=1}]}

 

这样不用外键的一对多,还有多对一就实现了

 

posted @ 2020-09-25 20:00  JOYBOY-007  阅读(188)  评论(0)    收藏  举报