MyBatis学习总结(3)

MyBatis学习总结大全:
- MyBatis学习总结第一天
- MyBatis学习总结第二天
- MyBatis学习总结第三天

今日大纲:

  • < resultMap> 使用
  • 多表查询四种方式
    一对一
    一对多
    多对多
    自关联
  • MyBatis注解开发
  • MyBatis 运行原理

多表操作
多表操作,当两个表中的字段名称一致,使用一次查询的时候,数据会混乱,所以在这种情况下,需要在写sql语句的时候,就将重复的字段进行别名设置,然后在resultMap中的column属性中的值为别名。
< resultMap>返回值集合
设计数据库的时候,不是所有数据库字段跟对象属性的命名规则一致。
userName ->USER_NAME
第一种:使用数据库别名关键字
第二种:< resultMap>标签

<mapper namespace="com.bjsxt.mapper.CardMapper">
    <!-- 
        定义的返回值集合
        type:为返回值类型
        id:在一个映射文件中的是唯一值
     -->
    <resultMap type="card" id="getCards">
        <!-- 对应的是数据库表的主键 -->
        <id column="card_id" property="cardId"/>
        <!-- 对应的是数据除主键外的所有字段 -->
        <result column="card_name" property="cardName"/>

    </resultMap>
    <!-- extends:可以继承已有的 resultMap,类似于Java的继承,可以使用父resultMap的定义的属性-->
    <resultMap type="card" id="cards" extends="getCards">
        <result column="card_no" property="cardNo"/>
        <result column="user_id" property="userId"/>
    </resultMap>
    <!-- 
        id:必要信息,在一个映射文件中,要保证唯一
        resultType:如果使用resultMap,就省略,因为在resultMap已经定义返回类型
        resultMap:返回值集合,它的值为已定义的<resultMap>标签的id值对应
     -->
    <select id="findCards" resultMap="cards">
        select * from t_card
    </select>

    <!-- 第一种方式:使用别名解决数据库表字段与对象属性不一致问题 -->
    <select id="getCards" resultType="card">
        select 
            card_id as cardId,
            card_name as cardName,
            card_no as cardNo,
            user_id as userId
        from t_card 

    </select>
  </mapper>

接口

public interface CardMapper {

    List<Card> getCards();

    List<Card> findCards();
}

测试

/**
     * 
     * @Description:   别名查询
     * @author mao
     * @date   2017年10月12日
     */
    @Test
    public void getCards(){
        CardMapper mapper = session.getMapper(CardMapper.class);
        List<Card> cards = mapper.getCards();
        for (Card card : cards) {
            System.out.println(card);
        }
    }
    /**
     * 
     * @Description: 使用resultMap  
     * @author mao
     * @date   2017年10月12日
     */
    @Test
    public void findCards(){

        CardMapper mapper = session.getMapper(CardMapper.class);
        List<Card> findCards = mapper.findCards();
        for (Card card : findCards) {
            System.out.println(card);
        }

    }

一对一
数据库的表的一对一关系在mybatis中怎么应用。一个用户只有一个身份证:
T_user 用户表
T_card 身份证表,我将用户的id作为外键保存身份证表中

--一对一查询的sql,两种方式
select t.*,c.* from t_user t,t_card c where t.id = c.USER_ID;

select * from t_card ; 
select * from t_user where id=2;

1.在card对象中,创建用户的对象,构建他们的关系
2.在映射文件中构建card与用户表对应及查询关系

CardMapper.xml

<mapper namespace="com.bjsxt.mapper.CardMapper">

    <resultMap type="card" id="card">
        <id column="card_id" property="cardId"/>
        <result column="card_name" property="cardName"/>
        <result column="card_no" property="cardNo"/>
        <result column="user_id" property="userId"/>
    </resultMap>

    <resultMap type="card" id="cards" extends="card">
        <!-- 处理关联的一对一对象
            property:对应的是关联对象的属性名称
            javaType:对应的是关联对象的类型
            resultMap:如果,该resultMap在同一个映射文件中,直接使用resultMap的id值
                        如果,不在同一个映射文件中,使用:namespace.resultMap的id
         -->
        <association property="user" javaType="user" 
            resultMap="com.bjsxt.mapper.UserMapper.users">
        </association>
    </resultMap>
    <!-- 第一种:处理一对一的数据关联 ,一次查询-->
    <select id="getCards" resultMap="cards">
        select u.*,c.* from t_user u,t_card c where u.id = c.user_id
    </select>

    <resultMap type="card" id="card2" extends="card">
        <!-- 
            select:对应的是关联查询的select语句,值为select标签的id值
                如果,查询select语句在同一个映射文件中,直接使用其id值
                如果不在,使用select语句的,namespace.select的id值
            column:放置外键,对应查询目标表的主键
         -->
        <association property="user" javaType="user" 
                select="com.bjsxt.mapper.UserMapper.getUsersById" column="user_id">
        </association>
    </resultMap>

    <!--第二种方式:n+1查询  -->
    <select id="getCards2" resultMap="card2">
        select * from t_card 
    </select>

  </mapper>

UserMapper.xml

<mapper namespace="com.bjsxt.mapper.UserMapper">

    <resultMap type="user" id="users">
        <id column="id" property="id"/>
            <result column="name" property="name"/>
            <result column="pwd" property="pwd"/>
            <result column="age" property="age"/>
    </resultMap>
        <!-- 接收参数的id :随便写 -->
    <select id="getUsersById" resultMap="users">
        select * from t_user where id=#{id}
    </select>

    <select id="getUsers" resultType="user">
        select * from t_user 
            <where>
                <if test="name != null and name != ''">
                    and name = #{name}
                </if>
                <choose>
                    <when test="pwd != null and pwd != ''">
                        and pwd = #{pwd}
                    </when>
                    <otherwise>
                        and 1=1
                    </otherwise>
                </choose>
            </where>
    </select>

    <select id="findUsers" resultType="user">
        select * from t_user
            <where>
                id in
                <foreach collection="list" open="(" separator="," close=")" item="ids">
                    #{ids}
                </foreach>
            </where>
    </select>

    <update id="updateUser">
        update t_user
            <set>
                <if test="name != null and name != ''">
                    name = #{name}
                </if>
            </set>
            where id=#{id}
    </update>

</mapper>

测试:

    /**
     * 
     * @Description:  一对一查询 
     * 第一方式:一次查询
     * @author mao
     * @date   2017年10月12日
     */
    @Test
    public void getCards(){
        CardMapper mapper = session.getMapper(CardMapper.class);
        List<Card> cards = mapper.getCards();
        for (Card card : cards) {
            System.out.println(card);
        }
    }
    /**
     * 
     * @Description: 一对一关系:  n+1查询
     * @author mao
     * @date   2017年10月12日
     */
    @Test
    public void getCards2(){
        CardMapper mapper = session.getMapper(CardMapper.class);
        List<Card> cards2 = mapper.getCards2();
        for (Card card : cards2) {
            System.out.println(card);
        }
    }

一对多
数据库中一对多表关系,在mybatis的中的应用,数据库设计中,一个用户对应多本书。
用户表主键在书籍表中是外键,
书籍查询用户的信息:解决方案见:一对一
用户查询书籍的时候:

--n+1次查询sql
select * from t_user;
SELECT * FROM `t_book` where uesr_id = id;
--一次查询sql
select u.*,b.* from t_user u LEFT JOIN t_book b on u.ID = b.USER_ID;

UserMapper.xml

<mapper namespace="com.bjsxt.mapper.UserMapper">
    <!-- user的resultMap -->
    <resultMap type="user" id="getUser">
            <id column="id" property="id"/>
            <result column="name" property="name"/>
            <result column="pwd" property="pwd"/>
            <result column="age" property="age"/>
    </resultMap>

    <resultMap type="user" id="getUsers" extends="getUser">
        <!-- 构建一对多的关系
            一个用户对应多个书籍
            collection:用于处理一对多的关系的标签
            property:对象中的管理对象的属性名称
            javaType:使用集合类型
            ofType:指的是集合的泛型对象类型
            select:引用select语句,
                如果该select在同一个映射文件中,直接使用select的id
                如果该select不在同一个映射文件中,使用namespace.select的id
            column:给select语句传递参数,select要的参数
                select的参数命名,随便名称,但是如果该select还有其他方法调用,命名一定要规则
         -->
         <collection property="books" javaType="list" ofType="book" 
            select="com.bjsxt.mapper.BookMapper.getBooks"   
            column="id"
         ></collection>
    </resultMap>
    <!-- 
        一般情况下:
        n+1次查询:使用select 属性
        一次查询:使用resultMap
     -->
    <resultMap type="user" id="getUsers1" extends="getUser">
        <collection property="books" javaType="list" ofType="book" 
            resultMap="com.bjsxt.mapper.BookMapper.getBook"></collection>
    </resultMap>

    <select id="getUsers" resultMap="getUser">
        SELECT * FROM t_user where id= #{id}
    </select>
    <!-- 一对多的: n+1次查询 -->
    <select id="getUsers1" resultMap="getUsers">
        select * from t_user
    </select>

    <!-- 一对多的:一次查询 -->
    <select id="getUsers2" resultMap="getUsers1">
        select u.*,b.* 
            from    t_user u 
                LEFT JOIN 
                    t_book b 
                on 
                    u.ID=b.user_id
    </select>
  </mapper>

BookMapper.xml

  <mapper namespace="com.bjsxt.mapper.BookMapper">

    <resultMap type="book" id="getBook">
        <id column="book_id" property="bookId"/>
        <result column="book_name" property="bookName"/>
        <result column="user_id" property="userId"/>
    </resultMap>

    <select id="getBooks" resultMap="getBook">
        select * from t_book where user_id = #{id}
    </select>
  </mapper>

测试:

    /**
     * 
     * @Description:   一对多的 一次查询
     * @author mao
     * @date   2017年10月12日
     */
    @Test
    public void getUsers(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User userByIds = mapper.getUserByIds(2);
        System.out.println(userByIds);
    }

    /**
     * 
     * @Description:   一对多的 n+1此查询
     * @author mao
     * @date   2017年10月12日
     */
    @Test
    public void getUsers3(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User userById3 = mapper.getUserById3(2);
        System.out.println(userById3);

    }

多对多
数据库中多对多表关系,在mybatis的中的应用,一个学生对应多个课程,一个课程可以对应多个学生。一个学生表、一个课程表、一个中间表。

SELECT c.*,s.* FROM T_CLASS c,t_student s , t_student_class sc 
where c.C_ID=sc.C_ID and s.S_ID = sc.S_ID

SELECT * from t_class 
select * from t_student s ,t_student_class sc where s.S_ID = sc.S_ID and sc.C_ID=

StudentMapper.xml

<mapper namespace="com.bjsxt.mapper.StudentMapper">

    <resultMap type="student" id="student">
        <id column="s_id" property="id"/>
        <result column="s_name" property="name"/>
        <result column="s_sex" property="sex"/>
        <result column="s_no" property="no"/>
    </resultMap>

    <resultMap type="student" id="students" extends="student">
        <collection property="classesList" javaType="list" ofType="classes" 
            resultMap="com.bjsxt.mapper.ClassesMapper.classes">
        </collection>
    </resultMap>
    <!-- 多对多 一次查询 -->
    <select id="getStudents" resultMap="students">
        SELECT c.*,s.* 
        FROM 
            T_CLASS c,
            t_student s , 
            t_student_class sc 
        where 
            c.C_ID=sc.C_ID 
            and 
            s.S_ID = sc.S_ID
    </select>

    <resultMap type="student" id="findstudent" extends="student">
        <collection property="classesList" javaType="list" ofType="classes"
            select="com.bjsxt.mapper.ClassesMapper.getClasses" column="s_id">
            </collection>
    </resultMap>
    <!--  多对多 n+1次查询-->
    <select id="findStudents" resultMap="findstudent">
        select * from t_student 
    </select>
  </mapper>

ClassesMapper.xml

<mapper namespace="com.bjsxt.mapper.ClassesMapper">

    <resultMap type="classes" id="classes">
        <id column="c_id" property="id"/>
        <result column="c_name" property="name"/>
        <result column="c_no" property="no"/>
    </resultMap>

    <select id="getClasses" resultMap="classes">
        select s.* 
            from 
                t_class s ,
                t_student_class sc 
            where 
                s.c_id = sc.c_id
                and sc.S_id = #{id}
    </select>

  </mapper>

测试类:

    private SqlSession session;

    @Before
    public void getSession(){
        session = MybatisUtil.getSession();

    }
    @After
    public void closeSession(){
        MybatisUtil.closeSession();
    }
    /**
     * 
     * @Description:   多对多查询
     * @author mao
     * @date   2017年10月12日
     */
    @Test
    public void getStudent(){

        StudentMapper mapper = session.getMapper(StudentMapper.class);
        List<Student> students = mapper.getStudents();
        for (Student student : students) {
            System.out.println(student);
        }

    }
    /**
     * 
     * @Description:   多对多查询 :n+1次查询
     * @author mao
     * @date   2017年10月12日
     */
    @Test
    public void findStudents(){
        StudentMapper mapper = session.getMapper(StudentMapper.class);
        List<Student> findStudents = mapper.findStudents();
        for (Student student : findStudents) {
            System.out.println(student);
        }
    }

}

Student.java

private Integer id;

    private String name;

    private String sex;

    private String no;

    private List<Classes> classesList;
//自行生成对应getter/setter方法

1.5自关联
在数据表的一张表中,构建层级关系,一般有一个字段作为定义层级,最高级只有一个。
配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

  <mapper namespace="com.bjsxt.mapper.CityMapper">

    <resultMap type="city" id="city">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="parent_id" property="parentId"/>
    </resultMap>

    <resultMap type="city" id="getCity" extends="city">
        <collection property="citys" javaType="list" ofType="city" 
            select="getCitys1"
            column="id"
        ></collection>
    </resultMap>

    <!-- 找到根数据 -->
    <select id="getCitys" resultMap="getCity">
        select * from t_city where parent_id = 0
    </select>
    <!-- 找到他的一级子节点 -->
    <select id="getCitys1" resultMap="city">
        select * from t_city where parent_id=#{id}
    </select>
    <!-- 使用代码,解决自关联 -->
    <select id="getCitys2" resultMap="city">
        select * from t_city
    </select>
  </mapper> 
实现类:
/**
 * 
* @ClassName:TestCity
* @Description:测试 自连接
* @Company: 北京尚学堂科技有限公司 www.bjsxt.com
* @author mao
* @date 2017年10月31日
 */
public class TestCity {

    private SqlSession session;

    @Before
    public void getSession(){
        session = MybatisUtil.getSession();
    }
    @After
    public  void closeSession(){
        MybatisUtil.closeSession();
    }

    /**
     * 代码实现自关联
     * 1.查询所有的数据
     * 2.在代码中使用循环来创建关联关系
     */
    @Test
    public void getCitys1(){

        CityMapper mapper = session.getMapper(CityMapper.class);

        List<City> citys2 = mapper.getCitys2();

        City root = null;

        for (City city : citys2) {
            //当数据的父主键为0的时候,说明该city为根节点
            if(city.getParentId().equals(0)){
                root = city;
            }
            for (City city1 : citys2) {
                if(city.getId().equals(city1.getParentId())){
                    city.getCitys().add(city1);
                }
            }
        }

        System.out.println(root);
    }

    /**
     * 
     * @Description:自关联   
     * 使用一对多的关系来处理自关联
     * 如果层级多的话,很难实现
     * @author mao
     * @date   2017年10月31日
     */
    @Test
    public void getCitys(){
        CityMapper mapper = session.getMapper(CityMapper.class);
        City citys = mapper.getCitys();
        System.out.println(citys);
    }
}

注解开发
注解开发是web3.0之后提出的标准,它主要目的就在代码不使用配置文件(xml)或者尽可能的不使用配置文件。
Mybatis的注解开发,在实际项目中,不怎么经常使用,因为在配置文件中写sql语句,比使用注解写sql要简单、明了。Mybatis的注解开发处理复杂逻辑,很费劲。
注解一般写在方法、类、变量的上面进行标识

public interface UserMapper {

    /**
     * 查询所有用户信息
     * 1.简单类型的参数传递
     * 2.对象类型
     * 3.map类型
     */
    @Select(value="select * from t_user where id= #{id}")
    List<User> getUsers(Integer id);
    /**
     * 新增
     * 如果注解中只有一个value属性的话,value可以省略
     * @SelectKey:
     *      resultType:返回值类型Class<?> ,java.lang.Integer.class
     *      before:返回值是 boolean,如果是值true,表示是在执行sql语句之前执行,
     *                          如果值false:表在sql执行之后执行
     *      keyColumn:对应数据库的表主键
     *      keyProperty:对应的是对象的主键
     *      statement:要执行的sql语句
     */
    @Insert("insert into t_user(name,pwd,age) values(#{name},#{pwd},#{age})")
    @SelectKey(resultType=java.lang.Integer.class,before=false,
        keyColumn="id",keyProperty="id",statement="select @@identity as id")
    int saveUser(User user);

    /**
     * 修改
     */
    @Update("update t_user set name=#{name} , age=#{age} where id=#{id}")
    int updateUser(User user);

    /**
     * 删除
     */
    @Delete("delete from t_user where id=#{id}")
    int deleteUser(Integer id);
}

测试类:

    /**
     * 
     * @Description: 注解开发,查询  
     * @author mao
     * @date   2017年10月13日
     */
    @Test
    public void getUsers(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users = mapper.getUsers(2);
        for (User user : users) {
            System.out.println(user);
        }
    }
    /**
     * 
     * @Description:  注解开发 新增 
     * @author mao
     * @date   2017年10月13日
     */
    @Test
    public void saveUser(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User("张000", "zhang000", 44);
        int saveUser = mapper.saveUser(user);
        session.commit();
        System.out.println(saveUser);
        System.out.println(user);
    }
    /**
     * 
     * @Description: 注解开发 修改数据   
     * @author mao
     * @date   2017年10月13日
     */
    @Test
    public void updateUser(){
        UserMapper mapper = session.getMapper(UserMapper.class);
        User user = new User();
        user.setName("赵6666");
        user.setAge(55);
        user.setId(32);
        int updateUser = mapper.updateUser(user);
        session.commit();
        System.out.println(updateUser);

    }
    /**
     * 
     * @Description:  注解开发  删除
     * @author mao
     * @date   2017年10月13日
     */
    @Test
    public void deleteUser(){

        UserMapper mapper = session.getMapper(UserMapper.class);
        int deleteUser = mapper.deleteUser(32);
        session.commit();
        System.out.println(deleteUser);

    }

Mybatis.cfg.xml,中mapper文件的引用还是包引用

    <mappers>
        <!-- <mapper resource="com/bjsxt/mapper/user.mapper.xml"/> -->

        <package name="com.bjsxt.mapper"/>
    </mappers>

运行原理
MyBatis内部原理机制参考博客:
http://blog.csdn.net/column/details/mybatis-principle.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Anguser

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值