Mybatis总结

这篇博客详细总结了Mybatis的使用经验,包括多个参数查询、模糊查询、实际应用场景、Session工厂创建、一对一和一对多关系映射,以及动态SQL的运用。还特别提到了在增删改操作中如何灵活运用select标签,并指出类属性与表字段一致时可简化resultMap映射,以及返回集合时的类型设定规范。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.多个参数的查询:

User queryNameandAddress(@Param("name") String name,@Param("address")String address);

<select id="queryNameandAddress" resultType="User">
    SELECT * FROM user where name = #{name} and address = #{address}
  </select>

2.模糊查询:

<!-- (1)方法一:返回结果只有一个时候,参数只有一个-->
<select id="findByName" resultType="User">
    select * from user where name like #{name}
  </select>
  User findByName(String name);

     <!-- 方法二:根据用户名称模糊查询用户信息,可能返回多条 resultType:指定就是单条记录所映射的java对象 类型 ${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中。   
        使用${}拼接sql,引起 sql注入 ${value}:接收输入 参数的内容,如果传入类型是简单类型,${}中只能使用value -->  
    <select id="findUserByName" parameterType="java.lang.String"  
        resultType="user">  
        SELECT * FROM USER WHERE username LIKE '%${value}%'  
    </select>  
    public List<User> findUserByName(String name) throws Exception;  

<!-- (2)模糊查询参数多个时-->
 <select id="queryNameandAddress2" resultType="User">
    <bind name="namePattern" value="'%' + _parameter.name + '%'"/>
    <bind name="nameAddress" value="'%' + _parameter.address + '%'"/>
    select * from user where name like #{namePattern} and address like #{nameAddress}
  </select>
  User queryNameandAddress2(@Param("name") String name,@Param("address")String address);

<!-- MySQL分页一:-->
<select id="fenYe1" resultType="User">
    select * from user order by id offset #{offset} limit #{limit}
  </select>
List<User> fenYe1(@Param("offset") int offset,@Param("limit") int limit);

<!-- MySQL分页二:-->
<!-- 返回类型为集合时 不需要写集合类型,直接写集合中对应实体的类型 -->
<select id="fenye2" resultType="User">
    select * from user order by id
  </select>

  List<User> fenye2(RowBounds rowBounds);

List<User> fenye2 = mapper.fenye2(new RowBounds(2, 2));

<!-- 再插入一条数据时,获取他的主键-->
    <!-- #{}中指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值 parameterType="user" user为别名-->  
    <insert id="insertUser" parameterType="user">  
        <!-- SELECT LAST_INSERT_ID():得到刚insert进去记录的主键值,只适用与自增主键 -->  
        <!-- keyProperty:将查询到主键值设置到parameterType指定的对象的哪个属性 -->  
        <!-- order:SELECT LAST_INSERT_ID()执行顺序,相对于insert语句来说它的执行顺序 -->  
        <!-- resultType:指定SELECT LAST_INSERT_ID()的结果类型 -->  
        <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">  
            <!-- 将插入数据的主键返回,返回到user对象中 -->  
            SELECT LAST_INSERT_ID()  
        </selectKey>  
        insert into user(username,birthday,sex,address)  
        value(#{username},#{birthday},#{sex},#{address})  
        <!-- 使用mysql的uuid()生成主键 执行过程: -->  
        <!-- 首先通过uuid()得到主键,将主键设置到user对象的id属性中 其次在insert执行时,从user对象中取出id属性值 -->  
        <!-- <selectKey keyProperty="id" order="BEFORE" resultType="java.lang.String"> -->  
        <!-- SELECT uuid() </selectKey> insert into user(id,username,birthday,sex,address) -->  
        <!-- value(#{id},#{username},#{birthday},#{sex},#{address}) -->  
    </insert>  

3 mybatis实际应用:

<?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命名空间,作用就是对sql进行分类化管理,理解sql隔离 -->  
<!-- 注意:使用mapper代理方法开发,namespace有特殊重要的作用,namespace等于mapper接口地址 -->  
<mapper namespace="cn.com.mybatis.mapper.UserMapper">  

    <!-- 定义sql片段 -->  
    <!-- id:sql片段的唯 一标识 -->  
    <!-- 经验:是基于单表来定义sql片段,这样话这个sql片段可重用性才高 在sql片段中不要包括 where -->  
    <sql id="query_user_where">  
        <if test="userCustom!=null">  
            <if test="userCustom.sex!=null and userCustom.sex!=''">  
                and user.sex = #{userCustom.sex}  
            </if>  
            <if test="userCustom.username!=null and userCustom.username!=''">  
                and user.username LIKE '%${userCustom.username}%'  
            </if>  
        </if>  
    </sql>  

    <!-- 已经指定好别名! -->  
    <!-- 运用sql片段   -->  
    <!-- 用户信息综合查询 #{userCustom.sex}:取出pojo包装对象中性别值  -->  
    <!-- ${userCustom.username}:取出pojo包装对象中用户名称 -->  
    <select id="findUserList" parameterType="UserQueryVo"  
        resultType="UserCustom">  
        SELECT * FROM USER  
        <!-- where可以自动去掉条件中的第一个and -->  
        <where>  
            <!-- 引用sql片段 的id,如果refid指定的id不在本mapper文件中,需要前边加namespace -->  
            <include refid="query_user_where"></include>  
            <!-- 在这里还要引用其它的sql片段 -->  
        </where>  
    </select>  

    <!-- 用户信息综合查询总数 parameterType:指定输入类型和findUserList一样 resultType:输出结果类型 -->  
    <select id="findUserCount" parameterType="UserQueryVo"  
        resultType="int">  
        SELECT count(*) FROM USER  
        <!-- where可以自动去掉条件中的第一个and -->  
        <where>  
            <!-- 引用sql片段 的id,如果refid指定的id不在本mapper文件中,需要前边加namespace -->  
            <include refid="query_user_where"></include>  
            <!-- 在这里还要引用其它的sql片段 -->  
        </where>  
    </select>  

    <!-- 在 映射文件中配置很多sql语句 -->  
    <!-- 需求:通过id查询用户表的记录 -->  
    <!-- 通过 select执行数据库查询 -->  
    <!-- id:标识 映射文件中的 sql -->  
    <!-- 将sql语句封装到mappedStatement对象中,所以将id称为statement的id -->  
    <!-- parameterType:指定输入 参数的类型,这里指定int型 -->  
    <!-- #{}表示一个占位符号 -->  
    <!-- #{id}:其中的id表示接收输入 的参数,参数名称就是id,如果输入 参数是简单类型,#{}中的参数名可以任意,可以value或其它名称 -->  
    <!-- resultType:指定sql输出结果 的所映射的java对象类型,select指定resultType表示将单条记录映射成的java对象。 -->  
    <!-- mapper开发代理规范2:UserMapper 接口中的接口方法名跟id名一样 -->  
    <!-- mapper开发代理规范3:UserMapper 接口中的返回类型名跟resultType类型一样 -->  
    <!-- mapper开发代理规范 4:UserMapper 接口中的参数类型名跟parameterType类型一样 -->  
    <select id="findUserById" parameterType="int" resultType="user">  
        SELECT * FROM USER WHERE id=#{value}  
    </select>  

    <!-- 根据用户名称模糊查询用户信息,可能返回多条 resultType:指定就是单条记录所映射的java对象 类型 ${}:表示拼接sql串,将接收到参数的内容不加任何修饰拼接在sql中。   
        使用${}拼接sql,引起 sql注入 ${value}:接收输入 参数的内容,如果传入类型是简单类型,${}中只能使用value -->  
    <select id="findUserByName" parameterType="java.lang.String"  
        resultType="user">  
        SELECT * FROM USER WHERE username LIKE '%${value}%'  
    </select>  



    <!-- 定义resultMap -->  
    <!-- 如果类的属性名与表的字段名称一样,则可以省略 resultMap映射 -->
    <!-- 将SELECT id id_,username username_ FROM USER 和User类中的属性作一个映射关系 -->  
    <!-- type:resultMap最终映射的java对象类型,可以使用别名 -->  
    <!-- id:对resultMap的唯一标识 -->  
    <resultMap type="user" id="userResultMap">  
        <!--id表示查询结果集中唯一标识 -->  
        <!--column:查询出来的列名 -->  
        <!--property:type指定的pojo类型中的属性名 最终resultMap对column和property作一个映射关系 (对应关系) -->  
        <id column="id_" property="id" />  
        <!--result:对普通名映射定义 -->  
        <!--column:查询出来的列名 -->  
        <!--property:type指定的pojo类型中的属性名 最终resultMap对column和property作一个映射关系 (对应关系) -->  
        <result column="username_" property="username" />  
    </resultMap>  

    <!-- 使用resultMap进行输出映射 -->  
    <!--resultMap:指定定义的resultMap的id,如果这个resultMap在其它的mapper文件,前边需要加namespace -->  
    <select id="findUserByIdResultMap" parameterType="int"  
        resultMap="userResultMap">  
        SELECT id id_,username username_ FROM USER WHERE id=#{value}  
    </select>  


</mapper>  

4 创建session的工厂(单例)

package mybatis;
import java.io.IOException;
import java.io.Reader;
import java.sql.Connection;
import javax.annotation.Resource;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MybatisUtil {
    private MybatisUtil(){}
    private static ThreadLocal<SqlSession> thread = new ThreadLocal<>();
    private static SqlSessionFactory sqlsessionfactory;
    static{
        try {
            Reader reader = Resources.getResourceAsReader("mybatis.cgf.xml");
            sqlsessionfactory = new SqlSessionFactoryBuilder().build(reader);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }

    public static SqlSession getSqlSession(){
        SqlSession sqlsession = thread.get();
        if(sqlsession == null){
            sqlsession = sqlsessionfactory.openSession();
            thread.set(sqlsession);
        }
        return sqlsession;
    }

    public static void closeSqlSession(){
        SqlSession sqlsession = thread.get();
        if(sqlsession!=null){
            sqlsession.close();
            thread.remove();
        }
    }
    /*public static void main(String[] args) {
        Connection conn = MybatisUtil.getSqlSession().getConnection();
        System.out.println(conn == null?"failed":"success");
    }*/

}

5 一对一,一对多:

<select id="findByID" resultMap="blogid">
        select b.id blog_id,a.id author_id,b.title blog_title,a.name author_name 
        from author a inner join blog b 
        on a.id = b.id 
        where b.id = #{id}
    </select>

    <resultMap type="Blog" id="blogid">
        <id property="id" column="blog_id"/>
        <result property="title" column="blog_title"/>
        <!-- 链接另外一张表(一对一) -->
        <association property="author" javaType="Author">
            <id property="id" column="author_id"/>
            <result property="name" column="author_name"/>
        </association>
    </resultMap>

    <!-- one2many -->

    <select id="findByID2" resultMap="blogid2">
        select b.id blog_id,b.title blog_title,
          a.id author_id,a.name author_name ,
          p.subject post_subject,p.id post_id
        from author a inner join blog b 
        on b.id = a.blog_id 
        left join post p
        on b.id = p.blog_id
        where b.id = #{id}
    </select>

    <resultMap type="Blog" id="blogid2">
        <id property="id" column="blog_id"/>
        <result property="title" column="blog_title"/>
        <association property="author" javaType="Author">
            <id property="id" column="author_id"/>
            <result property="name" column="author_name"/>
        </association>
        <!-- collection(ofType)一对多  类型也不同余association(javaType) -->
        <collection property="postlist" ofType="Post">
            <id property="id" column="post_id"/>
            <result property="subject" column="post_subject"/>
        </collection>
    </resultMap>

6 注意:

  • 增 删改 的时候 也可以用select 他会以sql为准 ,但是增删改用自己的标签时不能加返回类型,会报错
  • 如果类的属性名与表的字段名称一样,则可以省略 resultMap映射
  • 返回类型为集合时 不需要写集合类型,直接写对应实体的类型

    7.动态sql:

<!-- 动态查询 -->
    <select id="dongtaiquery" parameterType="map" resultMap="empMap">
        select * from emp
        <where>
            <if test="pid!=null">
                and id = #{pid}
            </if>
            <if test="pname!=null">
                and name = #{pname}
            </if>
            <if test="psalary!=null">
                and salary = #{psalary}
            </if>
        </where>
    </select>

    <!-- 动态更新 -->
    <update id="dongtaiUpdate" parameterType="map">
        update emp
        <set>
            <if test="pname!=null">
                name=#{pname}, 
            </if>
            <if test="psalary!=null">
                salary=#{psalary},
            </if>
        </set>
        where id=#{pid}
    </update>

    <!-- 动态删除  数组传参-->
    <delete id="dongtaidelete">
        delete from emp where id in
        <foreach collection="array" open="(" close=")" separator="," item="ids">
            #{ids}
        </foreach>
    </delete>

    <!-- 动态删除  集合传参 -->
    <delete id="dongtaidelete2">
        delete from emp where id in
        <foreach collection="list" open="(" close=")" separator="," item="ids">
            #{ids}
        </foreach>
    </delete>

    <!-- 动态插入数据  <include refid=""/> 为sql代码块 -->
    <insert id="dongtaiInsert" parameterType="mybatis.Emp">
        insert into emp(<include refid="key"/>) values(<include refid="value"/>)
    </insert>
    <!-- 表的插入字段 -->
    <sql id="key">
        <trim suffixOverrides=",">
            <if test="id!=null">
                id,
            </if>
            <if test="name!=null">
                name,
            </if>
            <if test="salary!=null">
                salary,
            </if>
        </trim>
    </sql>

    <!-- 表的插入字段所对应的值 -->
    <sql id="value">
        <trim suffixOverrides=",">
            <if test="id!=null">
                #{id},
            </if>
            <if test="name!=null">
                #{name},
            </if>
            <if test="salary!=null">
                #{salary},
            </if>
        </trim>
    </sql>
<!-- 测试-->
/**
     * 动态根据id删除  
     * @param ids  数组的形式传参
     */
    public void dongtaidelete(int... ids){
        SqlSession sqlsession = null;
        try {
            sqlsession = MybatisUtil.getSqlSession();
            sqlsession.delete("mybatis.Emp.dongtaidelete", ids);
            sqlsession.commit();
            System.out.println("success");
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

    /**
     * 动态根据id删除  
     * @param ids  集合的形式传参
     */
    public void dongtaidelete2(List<Integer> ids){
        SqlSession sqlsession = null;
        try {
            sqlsession = MybatisUtil.getSqlSession();
            sqlsession.delete("mybatis.Emp.dongtaidelete2", ids);
            sqlsession.commit();
            System.out.println("success");
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

    /**
     * 动态插入数据
     * @param ids
     */
    public void dongtaiInsert(Emp emp){
        SqlSession sqlsession = null;
        try {
            sqlsession = MybatisUtil.getSqlSession();
            sqlsession.delete("mybatis.Emp.dongtaiInsert", emp);
            sqlsession.commit();
            System.out.println("success");
        } catch (Exception e) {
            e.printStackTrace();
            sqlsession.rollback();
            throw e;
        }finally{
            MybatisUtil.closeSqlSession();
        }
    }

    public static void main(String[] arg){
        DongtaiDel dao = new DongtaiDel();
        /*dao.dongtaidelete(1,3,5);*/

        /*List<Integer> ids = new ArrayList<>();
        ids.add(2);
        ids.add(4);
        dao.dongtaidelete2(ids);*/

        //dao.dongtaiInsert(new Emp(1,"zhangsan",123.0));
        //dao.dongtaiInsert(new Emp(2,"lisi",null));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值