MyBatis(下)

Mybatis


多表查询

笛卡儿积查询

内连接查询

外连接查询

左外连接查询

右外连接查询

全外连接查询

一对一

在任意一方设计外键保存另一张表的主键,维系表和表的关系

创建sql语句
create table room(id int primary key,name varchar(255));
insert into room values (1,'梅花屋'),(2,'兰花屋'),(3,'桃花屋');
create table grade(id int primary key,name varchar(255), rid int);
insert into grade values (999,'向日葵班',2),(888,'玫瑰花班',3),(777,'菊花班',1);

 

Grade.java
public class Grade {
    private int id;
    private String name;
    private Room room;
}
Room.java
public class Room {
    private int id;
    private String name;
}
UserMapper.xml:映射文件
<!-- 一对一查询  -->
    <resultMap type="com.wiscom.domain.Grade" id="RM01">
        <id column="gid" property="id"/>
        <result column="gname" property="name"/>
        <association property="room" javaType="com.wiscom.domain.Room">
            <!-- 关联条件R_id对应G_id -->
            <id column="rid" property="id"/>
            <result column="rname" property="name"/>
        </association>
    </resultMap>
    
    <select id="s01" resultMap="RM01">
        select 
        room.id as rid,room.name as rname,grade.id as gid,grade.name as gname
        from 
        room inner join grade 
        on 
        room.id=grade.rid;
    </select>

 

TestDemo.java
package com.wiscom.test;
​
public class TestDemo {
    InputStream is = null;
    SqlSessionFactory ssf = null;
    SqlSession session = null;
    @Before
    public void demo() throws IOException{
        // 获取配置文件对应的字节输入流
        is = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 生成数据库连接
        ssf = new SqlSessionFactoryBuilder().build(is);
        
        // 获取会话
        session = ssf.openSession();
    }
    
    @Test
    public void test01() throws IOException{
        // 执行sql语句
        List list = session.selectList("com.wiscom.domain.UserMapper.s01");
        System.out.println(list);
    }
​
}
 

一对多

在多的一方设计外键保存一的一方的主键,维系表和表的关系

Dept.java
public class Dept {
    private int id;
    private String name;
    // 员工属性
    private List<Emp> list;
}
Emp.java
public class Emp {
    private int id;
    private String name;
}
Emp2.java
public class Emp2 {
    private int id;
    private String name;
    private Dept2 dept;
}

 

UserMapper.xml:映射文件
<!-- 一对多查询   以部门角度处理问题 -->
    <resultMap type="com.wiscom.domain.Dept" id="RM02">
        <id column="did" property="id"/>
        <result column="dname" property="name"/>
        <collection property="list" ofType="com.wiscom.domain.Emp">
            <id column="eid" property="id"/>
            <result column="ename" property="name"/>
        </collection>
        
    </resultMap>
    
    <select id="s02" resultMap="RM03">
        select 
        dept.id as did,dept.name as dname,emp.id as eid,emp.name as ename 
        from
        dept inner join emp 
        on 
        dept.id=emp.deptid;
    </select>
    
    <!-- 多对一查询  以员工角度处理问题  -->
    <resultMap type="com.wiscom.domain.Emp2" id="RM03">
        <id column="eid" property="id"/>
        <result column="ename" property="name"/>
        <association property="dept" javaType="com.wiscom.domain.Dept2">
            <id column="did" property="id"/>
            <result column="dname" property="name"/>
        </association>
    </resultMap>
TestDemo.java
@Test
    public void test01() throws IOException{
        // 执行sql语句
        List list = session.selectList("com.wiscom.domain.UserMapper.s02");
        System.out.println(list);
    }

 

 

多对多

设计一张第三方关系表,存储两张表的主键的对应关系,将一个多对多拆成两个一对多来存储

Stu.java
public class Stu {
    private int id;
    private String name;
    // 一个学生有多个老师
    private List<Teacher> list;
}
Teacher.java
public class Teacher {
    private int id;
    private String name;
}
Teacher2.java
public class Teacher2 {
    private int id;
    private String name;    
    private List<Stu2> list;
}
Stu2.java
public class Stu2 {
    private int id; 
    private String name;
}
UserMapper.xml:映射文件
 <!--  多对多查询  以学生视角解决问题 -->
    <resultMap type="com.wiscom.domain.Stu" id="RM04">
        <id column="sid" property="id"/>
        <result column="sname" property="name"/>
        <collection property="list" ofType="com.wiscom.domain.Teacher">
            <id column="tid" property="id"/>
            <result column="tname" property="name"/>
        </collection>
    </resultMap>
    
    <!-- 多对多查询  以老师视角解决问题  -->
    <resultMap type="com.wiscom.domain.Teacher2" id="RM05">
        <id column="tid" property="id"/>
        <result column="tname" property="name"/>
        <collection property="list" ofType="com.wiscom.domain.Stu2">
            <id column="sid" property="id"/>
            <result column="sname" property="name"/>
        </collection>
    </resultMap>
    
    
    <select id="s03" resultMap="RM05">
        select
        stu.id as sid,stu.name as sname,teacher.id as tid,teacher.name as tname
        from
        stu inner join stu_teacher
        on
        stu.id=stu_teacher.sid
        inner join teacher
        on
        teacher.id=stu_teacher.tid
    </select>

 

Mybatis中的细节

别名标签

sqlMapConfig.xml
    <typeAliases>
        <typeAlias type="com.wiscom.domain.User" alias="Ailas_User"/>
    </typeAliases>
UserMapper.xml:映射文件
    <select id="queryAll" resultType="Alias_User">
        select * from user;
    </select>

sql的复用

<include refid="test"/>

如果某段sql语句的片段在映射文件中重复出现,`可以将其单独配置为一个引用,从而在需要时直接引用,减少配置量

UserMapper.xml:映射文件
    <sql id="test">
        select * from user
    </sql>
    <select id="selAll1" resultType="com.wiscom.domain.User">
        <include refid="test"/> where id = 3;
    </select>

 

Mybatis的缓存机制

缓存机制可以减轻数据库的压力,原理是在第一次查询时,将查询结果缓存起来,之后再查询同样的sql,不是真的去查询数据库,而是直接返回缓存中的结果。

缓存可以降低数据库的压力,但同时可能无法得到最新的结果数据

一级缓存,二级缓存

可以使用第三方工具实现缓存

Redis内存数据库

Mybatis提供的缓存机制来实现缓存

一级缓存

缓存只在事务中有效,只有第一次查询时真正去查库,之后的查询都是从缓存中获得数据,如果事务不同则缓存无效

二级缓存(一般不会使用)

缓存在全局有效,二级缓存作用时间长,可能造成的危害也大

Mybatis中的一级缓存

Mybatis中的一级缓存默认就是开启的无法关闭

Mybatis中的二级缓存

Mybatis中的二级缓存默认是关闭的

配置选项开启二级缓存

要被二级缓存必须要实现序列化接口

且一定要被提交事务

sqlMapConfig.xml
    <!-- 开启二级缓存 -->
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
UserMapper.xml:映射文件
    <!-- 二级缓存的开关 -->
<cache />
User.java
public class User implements Serializable{
    private int id;
    private String name;
    private int age;
}
接口的使用

接口的名字和映射文件的名字相同

接口中方法的名字和要调用的映射文件中的标签的id相同

方法的参数和被调用的标签中的sql中需要的参数对应

返回类型需要和sql中的匹配

接口的位置必须和映射文件的命名空间相同

UserMapper.xml
<!-- mapper的命名空间  -->
<mapper namespace="com.wiscom.domain.UserMapper"><select id="selAll" resultType="com.wiscom.domain.User">
        select * from user
    </select>
    
    <insert id="insOne">
        insert into user values(null,#{name},#{age});
    </insert>
    
</mapper>
com.wiscom.domain.UserMapper
package com.wiscom.domain;
​
public interface UserMapper {
    public List<User> selAll();
    public void insOne(User user);
}
​
TestDemo.java
package com.wiscom.test;
​
public class TestDemo {
    InputStream is = null;
    SqlSessionFactory ssf = null;
    @Before
    public void demo() throws IOException{
        // 获取配置文件对应的字节输入流
        is = Resources.getResourceAsStream("sqlMapConfig.xml");
        // 生成数据库连接
        ssf = new SqlSessionFactoryBuilder().build(is);
        
        // 获取会话
    }
    
    @Test
    public void test01() throws IOException{
        SqlSession session = ssf.openSession();
        // 通过接口获取映射对象
        UserMapper mapper = session.getMapper(UserMapper.class);
        // 通过映射对象调用方法并打印结果
        System.out.println(mapper.selAll());
    }
}

 

posted @ 2020-08-19 19:09  minnersun  阅读(134)  评论(0编辑  收藏  举报