Mybatis framework (summary)

1. Mybatis CRUD

Written using dynamic agent-based dao way

  • Procedure
    1. Create project into coordinates
    2. Create mybatis core profile
    3. Create a map file sql
    4. Preparation method dao interfaces and interface
    5. sql statement written

1 UserDao Interface

public interface UserDao {

	//保存用户
	void save(User user);

	//根据id更新用户
	void update(User user);

	//根据id删除用户
	void delete(int id);

	//查询所有用户
	List<User> findAllUsers();

	//查询所有用户
	List<User> findAllUsersResultMap();

	//根据id查询
	User findById(int id);

	//模糊查询:根据用户名进行模糊查询
	List<User> findByName(String username);

}

2 UserMapper.xml

<?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="cn.itcast.dao.UserDao">

    <!--保存用户
        #{} : 占位符
    -->
    <insert id="save" parameterType="cn.itcast.domain.User">
        insert into
          user (username,birthday,sex,address)
        values
          (#{username},#{birthday},#{sex},#{address})
    </insert>

    <!--更新用户-->
    <update id="update">
        update user SET
          username=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
        WHERE
          id=#{id}
    </update>

    <!--根据id删除用户
            parameterType: 传入的参数类型
                自定义的java对象:对象的权限定类名
                基本数据类型(包装类型和String):基本数据类型,不区分大小写
                可以省略
            占位符:#{}
                自定义的java对象:对象中的属性
                基本数据类型(包装类型和String):随便写

    -->
    <delete id="delete" parameterType="iNt">
        delete from user where id=#{id}
    </delete>

    <!--
        查询所有用户
            resultType : 需要将查询数据封装的对象类型
                语法:对象的权限定类名
                条件:查询的字段和对象的属性保持一致
    -->
    <select id="findAllUsers" resultType="cn.itcast.domain.User">
        select * from user
    </select>

    <!--
        属性名和查询字段不一直:不能用resultType描述返回值
        使用resultMap描述映射关系
        resultMap :
                id:唯一标志
                type:经过resultMap转化后的对象类型
         id标签:配置主键的映射关系
         result标签:配置普通属性的映射关系
            column:从字段抄
            property:从实体类抄
    -->

    <resultMap id="userMap" type="cn.itcast.domain.User">
        <!--主键-->
        <id column="_id" property="id"></id>
        <!--普通属性-->
        <result column="_name" property="username"></result>
        <result column="birthday" property="birthday"></result>
        <result column="userSex" property="sex"></result>
        <result column="abc" property="address"></result>
    </resultMap>

    <select id="findAllUsersResultMap" resultMap="userMap">
        SELECT id _id,username _name,birthday, sex userSex, address abc FROM USER
    </select>

    <!--根据id查询-->
    <select id="findById" parameterType="int" resultType="cn.itcast.domain.User">
        select * from user where id=#{id}
    </select>

    <!--

        模糊查询:根据用户名进行模糊查询
                SELECT * FROM USER WHERE username LIKE '%王%'

        #{} : 占位符
                自定义的java对象:对象中的属性  #{对象属性}
                基本数据类型(包装类型和String):#{随便写}
                使用preparedStatment处理占位符,经过预编译,没有sql注入的风险
        ${} : 字符串拼接
                自定义的java对象:对象中的属性  ${对象属性}
                基本数据类型(包装类型和String):${value}
                使用statment处理字符串拼接,不经过预编译,具有sql注入的风险
    -->
    <select id="findByName"  parameterType="string" resultType="cn.itcast.domain.User">
     select * from user where username like #{username}
    </select>
</mapper>
 namespace内填写: 接口的全限定名
 标签内的  id属性内:填写方法名
 标签内的  parameterType属性内:填写传入的参数类型
 标签内的  resultType : 需要将查询数据封装的对象类型 内填写对象的权限定类名
 sql语句内的  (?占位符)   使用#{对象的属性}来代替?
 resultMap标签:
         id:唯一标志  内容与select标签内的resultMap内的内容保持一致
         type:经过resultMap转化后的对象类型
         id标签:配置主键的映射关系
 result标签:配置普通属性的映射关系
         column:从字段抄
         property:从实体类抄
           模糊查询:根据用户名进行模糊查询
                SELECT * FROM USER WHERE username LIKE '%王%'

  #{} : 占位符
        自定义的java对象:对象中的属性  #{对象属性}
        基本数据类型(包装类型和String):#{随便写}
        使用preparedStatment处理占位符,经过预编译,没有sql注入的风险
  ${} : 字符串拼接
        自定义的java对象:对象中的属性  ${对象属性}
        基本数据类型(包装类型和String):${value}
        使用statment处理字符串拼接,不经过预编译,具有sql注入的风险

3 UserDaoTest

package cn.itcast.test;

import cn.itcast.dao.UserDao;
import cn.itcast.domain.User;
import cn.itcast.utils.BaseTestUtil;
import org.junit.Test;

import java.util.List;

public class UserDaoTest extends BaseTestUtil {

	//测试保存
	@Test
	public void testSave() {
		//1.创建dao接口的动态代理对象(实现类)
		UserDao userDao = session.getMapper(UserDao.class);
		//2.调用dao方法保存用户
		User user = new User();
		user.setUsername("lol");
		user.setAddress("初中");
		userDao.save(user);
	}

	//测试更新
	@Test
	public void testUpdate() {
		//1.创建动态代理对象
		UserDao userDao = session.getMapper(UserDao.class);
		//2.调用dao完成更新用户
		User user = new User();
		user.setUsername("lol1");
		user.setAddress("初中1");
		user.setId(229);
		userDao.update(user);
	}

	//测试删除
	@Test
	public void testDelete() {
		//1.创建动态代理对象
		UserDao userDao = session.getMapper(UserDao.class);
		//2.调用dao完成删除用户
		userDao.delete(229);
	}

	//测试查询全部
	@Test
	public void testFindAllUsers() {
		//1.创建动态代理对象
		UserDao userDao = session.getMapper(UserDao.class);
		//2.调用dao完成删除用户
		List<User> users = userDao.findAllUsers();
		for (User user : users) {
			System.out.println(user);
		}
	}

	//测试查询全部
	@Test
	public void testFindAllUsersResultMap() {
		//1.创建动态代理对象
		UserDao userDao = session.getMapper(UserDao.class);
		//2.调用dao完成删除用户
		List<User> users = userDao.findAllUsersResultMap();
		for (User user : users) {
			System.out.println(user);
		}
	}

	//测试根据id查询
	@Test
	public void testFindById() {
		//1.创建动态代理对象
		UserDao userDao = session.getMapper(UserDao.class);
		//2.调用dao
		User user = userDao.findById(228);
		System.out.println(user);
	}

	//测试模糊查询

	/**
	 * 方式一:(重点)
	 *      参数:查询条件在参数上进行的拼接
	 *      SQL: select * from user where username like #{username}
	 * 方式二:(不用)
	 *      参数:只传递数据 : 王
	 *      模糊查询条件:sql映射文件中拼接
	 *      SQL:  select * from user where username like "%"#{username}"%"
	 *       "%"#{username}"%":mysql语法中的字符串拼接
	 * 方式三:(不用)
	 *      参数:只传递数据 : 王
	 *      模糊查询条件:sql映射文件中拼接
	 *      mysql的函数方法  concat() ,对方法中的字符串拼接
	 *      sql语句: select * from user where username like concat('%',#{username},'%')
	 * 方式四:(不用)
	 *       参数:只传递数据 : 王
	 *       模糊查询条件:sql映射文件中拼接
	 *       使用${} 拼接
	 *        select * from user where username like '%${value}%'
	 */
	@Test
	public void testFindByName() {
		//1.创建动态代理对象
		UserDao userDao = session.getMapper(UserDao.class);
		//2.调用dao
		List<User> users = userDao.findByName("%王%");
		for (User user : users) {
			System.out.println(user);
		}
	}
}

2. Mybatis multi-parameter query to obtain the primary key dynamic SQL (focus on various labels) multi-table relationship (many-to-many)

1 UserDao Interface

package cn.itcast.dao;

import cn.itcast.domain.QueryVo;
import cn.itcast.domain.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserDao {
	/**
	 * 多个参数的查询:根据用户名和性别查询
	 *      方式一: 使用mybatis的默认参数别名(了解)
	 *          和传入的参数一一对应
	 *          第一个参数: arg0 或者 param1
	 *          第二个参数: arg1 或者 param2
	 */
	List<User> findByNameAndSex1(String username,String sex);

	/**
	 * 方式二: 使用@Param注解配置到方法参数之前,对传入的参数自定义别名
	 *          value:自定义的别名
	 */
	List<User> findByNameAndSex2(@Param("name") String username,@Param("userSex") String sex);

	/**
	 * 方式三:将多个参数封装到对象中
	 */
	List<User> findByNameAndSex3(User user);

	/**
	 * 保存用户
	 */
	void save(User user);

	/**
	 * 多条件查询
	 */
	List<User> findByUser(User user);

	/**
	 * 测试 choose , when otherwise
	 */
	List<User> findByUserChoose(User user);

	/**
	 * 更新用户
	 */
	void update(User user);

	/**
	 * 根据用户id的集合查询用户
	 */
	List<User> findByCollection(List<Integer> ids);

	/**
	 * 根据用户id的数组查询用户
	 */
	List<User> findByArray(int [] ids);

	/**
	 * 根据vo对象(封装了用户id的集合或者数组)查询用户
	 */
	List<User> findByVo(QueryVo vo);
}

2 UserMapper.xml

<?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="cn.itcast.dao.UserDao">

    <!--
        多个参数的查询:根据用户名和性别查询
    -->
    <select id="findByNameAndSex1" resultType="cn.itcast.domain.User">
        select * from user where  sex=#{arg1} and username=#{arg0}
    </select>

    <select id="findByNameAndSex2" resultType="cn.itcast.domain.User">
        select * from user where  sex=#{userSex} and username=#{name}
    </select>

    <select id="findByNameAndSex3" resultType="cn.itcast.domain.User" parameterType="cn.itcast.domain.User">
        select * from user where  sex=#{sex} and username=#{username}
    </select>

    <!--
        保存用户,获取保存之后的主键ID
            方式一: 使用useGeneratedKeys结合keyProperty获取
                useGeneratedKeys: 配置是否获取自动增长的id (false|true)
                keyProperty: 主键id需要赋值到的对象属性
            * 只能获取数据库中自动增长的id

    <insert id="save" useGeneratedKeys="true" keyProperty="id" parameterType="cn.itcast.domain.User">
        insert into user
          (username,birthday,sex,address)
        values
          (#{username},#{birthday},#{sex},#{address})
    </insert>
     -->

    <!--
        保存用户,获取保存之后的主键ID
             方式二: 先保存,再更新(last_insert_id())
                selectKey : 获取保存之后的主键id
                        order : 当前sql语句的执行顺序(BEFORE|AFTER)
                        resultType : 配置返回值类型
                        keyProperty :主键id需要赋值到的对象属性

    -->
    <insert id="save" useGeneratedKeys="true" keyProperty="id" parameterType="cn.itcast.domain.User">
      <selectKey order="AFTER" resultType="int" keyProperty="id">
          SELECT LAST_INSERT_ID()
      </selectKey>
        insert into user
        (username,birthday,sex,address)
        values
        (#{username},#{birthday},#{sex},#{address})
    </insert>

    <!--
        多条件查询
           动态sql:if标签
           String sql = "select * from user where 1=1"
           if(username!=null && username!=""){
                and username=?
           }
           if(sex!=null && sex!='') {
                and sex=?
           }
           动态sql:where标签
              用于SQL优化,根据判断体中的内容自动的添加where条件,
              对前面多余的and进行优化(删除)
    -->
    <select id="findByUser" parameterType="cn.itcast.domain.User" resultType="cn.itcast.domain.User">
      select * from user
        <!--<where>-->
          <trim prefix="where"  prefixOverrides="and">
            <if test="username!=null and username!=''">
                and username=#{username}
            </if>
            <if test="sex!=null and sex!=''">
                and sex=#{sex}
            </if>
          </trim>
       <!-- </where>-->
    </select>

    <!--
        动态sql: choose,when,otherwise
        相当于java代码中的  if,else if ,else
    -->
    <select id="findByUserChoose" parameterType="cn.itcast.domain.User" resultType="cn.itcast.domain.User">
      select * from user
        <where>
            <choose>
                <when test="username!=null and username!=''">
                    and username=#{username}
                </when>
                <when test="sex!=null and sex!=''">
                    and sex=#{sex}
                </when>
                <otherwise>
                    and id=45
                </otherwise>
            </choose>
        </where>
    </select>

    <!--
        更新用户
             动态sql: set
                添加更新的set语句,优化更新语句中最后多余的","
             动态sql:trim
                替换where和set
                    prefix : 自动生成标签,在判断体之前
                    suffix : 自动生成标签,在判断体之后
                    prefixOverrides : 优化SQL语句中前面多余的sql片段(, and)
                    suffixOverrides : 优化SQL语句中后面多余的sql片段(, and)
    -->
    <update id="update" parameterType="cn.itcast.domain.User">
        update user
           <!-- <set>-->
            <trim prefix="set"  suffixOverrides=",">
                <if test="username!=null and username!=''">
                    username=#{username},
                </if>
                <if test="birthday!=null">
                    birthday=#{birthday},
                </if>
                <if test="address!=null and address!=''">
                    address=#{address},
                </if>
                <if test="sex!=null and sex!=''">
                    sex=#{sex},
                </if>
            </trim>
           <!-- </set>-->
        where id=#{id}
    </update>
    
    
    <!--
        根据用户id的集合查询用户
        SQL: SELECT * FROM USER WHERE id IN (41,42,48)
        String sql = "SELECT * FROM USER  WHERE "
        sql+= "id IN (";
        for(Integer id : list) {
            sql+= id;
            sql+= ","
        }
        //处理多余的","(省略)
        sql+=")"
        动态sql : foreach标签(循环迭代)
              collection : 描述参数类型
                    传入集合数据类型: collection
                    传入数组类型(int[],String[]): array
                    传入的java对象(包含数组|集合属性): 数组|集合属性的名称
               open: 进入循环体之前执行的sql片段
               close: 执行循环体之后执行的sql片段
               item:对循环中每个元素设置别名
               separator: 拼接多个字符串的分割符号
    -->
    <select id="findByCollection" resultType="cn.itcast.domain.User">
      SELECT * FROM USER  WHERE
      <foreach collection="array" open="id IN (" close=")" item="id" separator=",">
          #{id}
      </foreach>
    </select>

    <!--
        传入数组
            collection : array
    -->
    <select id="findByArray" resultType="cn.itcast.domain.User">
        SELECT * FROM USER WHERE id in
        <foreach collection="collection" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </select>

    <!--
        传入java对象
            collection : 对象中集合或者属性的属性名
    -->
    <select id="findByVo" resultType="cn.itcast.domain.User" parameterType="cn.itcast.domain.QueryVo">
        SELECT * FROM USER WHERE id in
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </select>

</mapper>
**重要总结**
多参数查询:   推荐方式三:将多个参数封装到对象中
<select id="findByNameAndSex3" resultType="cn.itcast.domain.User" parameterType="cn.itcast.domain.User">
select * from user where  sex=#{sex} and username=#{username}
</select>


获取主键: 
方式一: 
insert标签内的: 
useGeneratedKeys: 配置是否获取自动增长的id (false|true)   相当于开关
keyProperty: 主键id需要赋值到的对象属性   	赋值的对象属性
* 只能获取数据库中自动增长的id
<insert id="save" useGeneratedKeys="true" keyProperty="id" parameterType="cn.itcast.domain.User">
insert into user
	(username,birthday,sex,address)
values
	(#{username},#{birthday},#{sex},#{address})
</insert>
方式二: 先保存再更新
selectKey : 获取保存之后的主键id
                order : 当前sql语句的执行顺序(BEFORE|AFTER)
                resultType : 配置返回值类型
                keyProperty :主键id需要赋值到的对象属性
 <selectKey order="AFTER" resultType="int" keyProperty="id">
          SELECT LAST_INSERT_ID()
 </selectKey>

动态sql(重点) 
在sql语句中完成判断,循环等java功能
1 if标签

2 where标签
	 用于SQL优化,根据判断体中的内容自动的添加where条件
     对前面多余的and进行优化(删除) 
     
3 choose when otherwise标签
	相当于java代码中的  if,else if ,else
	
4 set标签:   
作用更新用户
    动态sql: set
        添加更新的set语句,优化更新语句中最后多余的","

5 trim标签(了解)
trim标签主要作用:替换where和set标签   用于sql代码的优化

动态sql: set
       添加更新的set语句,优化更新语句中最后多余的","
动态sql:trim
       替换where和set
            prefix : 自动生成标签,在判断体之前
            suffix : 自动生成标签,在判断体之后
            prefixOverrides : 优化SQL语句中前面多余的sql片段(, and)
            suffixOverrides : 优化SQL语句中后面多余的sql片段(, and)
                    
6 foreach标签  
动态sql: foreach标签(循环迭代)
根据用户id的集合查询用户
        SQL: SELECT * FROM USER WHERE id IN (41,42,48)
        String sql = "SELECT * FROM USER  WHERE "
        sql+= "id IN (";
        for(Integer id : list) {
            sql+= id;
            sql+= ","
        }
        //处理多余的","(省略)
        sql+=")"
        动态sql : foreach标签(循环迭代)
              collection : 描述参数类型
                    传入集合数据类型: collection
                    传入数组类型(int[],String[]): array
                    传入的java对象(包含数组|集合属性): 数组|集合属性的名称
               open: 进入循环体之前执行的sql片段
               close: 执行循环体之后执行的sql片段
               item:对循环中每个元素设置别名 id
               separator: 拼接多个字符串的分割符号 ,

3 UserDaoTest

package cn.itcast.test;

import cn.itcast.dao.UserDao;
import cn.itcast.domain.QueryVo;
import cn.itcast.domain.User;
import cn.itcast.utils.BaseTestUtil;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class UserDaoTest extends BaseTestUtil {

	@Test
	public void testFindByNameAndSex() {
		//1.创建动态代理对象(dao接口的实现类)
		UserDao userDao = session.getMapper(UserDao.class);
		//2.操作数据库
		User user = new User();
		user.setSex("男");
		user.setUsername("老王");

		List<User> list = userDao.findByNameAndSex3(user);

		for (User user1 : list) {
			System.out.println(user1);
		}
	}

	//测试保存
	@Test
	public void testSave() {
		//1.创建动态代理对象(dao接口的实现类)
		UserDao userDao = session.getMapper(UserDao.class);
		//2.操作数据库
		User user = new User();
		user.setUsername("王者荣耀");
		user.setBirthday(new Date());
		user.setSex("女");
		user.setAddress("幼儿园");
		userDao.save(user);
		//获取保存之后的id
		System.out.println("主键="+user.getId());
	}

	//测试多条件查询(if标签)
	@Test
	public void testFindByUser() {
		User user = new User();
		user.setUsername("王者荣耀");
		user.setSex("女");

		//1.创建动态代理对象(dao接口的实现类)
		UserDao userDao = session.getMapper(UserDao.class);
		//2.操作数据库
		List<User> users = userDao.findByUser(user);
		for (User user1 : users) {
			System.out.println(user1);
		}
	}

	//测试choose,when,otherwise
	@Test
	public void testFindByUserChoose() {
		User user = new User();
		//user.setUsername("王者荣耀");
		//user.setSex("女");

		//1.创建动态代理对象(dao接口的实现类)
		UserDao userDao = session.getMapper(UserDao.class);
		//2.操作数据库
		List<User> users = userDao.findByUserChoose(user);
		for (User user1 : users) {
			System.out.println(user1);
		}
	}

	//测试更新
	@Test
	public void testUpdate() {
		User user = new User();
		user.setUsername("LOL1");
		user.setSex("男");
		user.setId(243);

		//1.创建动态代理对象(dao接口的实现类)
		UserDao userDao = session.getMapper(UserDao.class);
		//2.操作数据库
		userDao.update(user);
	}

	//测试foreach标签,传递集合
	@Test
	public void testFindByCollection() {
		List<Integer> ids = new ArrayList<>();
		ids.add(41);
		ids.add(42);
		ids.add(48);

		//1.创建动态代理对象(dao接口的实现类)
		UserDao userDao = session.getMapper(UserDao.class);
		//2.操作数据库
		List<User> list = userDao.findByCollection(ids);

		for (User user : list) {
			System.out.println(user);
		}
	}

	//测试foreach标签,传递数组
	@Test
	public void testFindByArray() {
		int [] ids = new int[]{41,42,48};

		//1.创建动态代理对象(dao接口的实现类)
		UserDao userDao = session.getMapper(UserDao.class);
		//2.操作数据库
		List<User> list = userDao.findByArray(ids);

		for (User user : list) {
			System.out.println(user);
		}
	}

	//测试foreach标签,传递对象
	@Test
	public void testFindByVo() {
		List<Integer> ids = new ArrayList<>();
		ids.add(41);
		ids.add(42);
		ids.add(48);
		QueryVo vo = new QueryVo();
		vo.setIds(ids);

		//1.创建动态代理对象(dao接口的实现类)
		UserDao userDao = session.getMapper(UserDao.class);
		//2.操作数据库
		List<User> list = userDao.findByVo(vo);

		for (User user : list) {
			System.out.println(user);
		}
	}
}

Guess you like

Origin blog.csdn.net/AdamCafe/article/details/90694347