mybatis复习


别名

一般有两种方式设置别名

  <typeAliases>
        <typeAlias type="com.zf.mybatis.pojo.User" alias="User"></typeAlias>
    </typeAliases>
    

常用的是用这样设置别名  将包下所有的类以类名作为
<package name="com.zf.mybatis.pojo"></package>

获取参数值的两种方式

#{} 占位符赋值,不会出现sql注入

${} 字符串拼接

案例

名字是aaa同样可以查到数据,跟变量名没关系

 <select id="getUserByName" resultType="User">
        select * from mybatis.t_user
        where username=#{aaa}
    </select>


${}使用,如果不加单引号会报错,名称无所谓
   <select id="getUserByName" resultType="User">
        select * from mybatis.t_user
        where username= '${username}'  
    </select>

案例2

多个参数的问题 mybatis会将多个数据放在一个map集合里边arg0,arg1,param0,param1

MyBatis获取参数值的各种情况:
1.mapper接口方法的参数为单个的字面量类型
可以通过${}和#{}以任意的名称获取参数值 但是需要注意${}的单引号问题
2、mapper接口方法的参数为多个时
此时MyBatis会讲这些参数放在一个map集合中,以两种方式进行存储
a>以arge, arg1…为键,以参数为值
b>以param1 , param2…为键,以参数为值
因此只需要通过#{}和{手以键的方式访问值即可,但是需要注意${}的单引号问题

3.若mybatis的方法多个参数是可以放在一个map集合中,这样mybatis不会再自定义arg0,arg1,param1,param2

4.mapper接口方法传的是一个对象时,直接通过属性名来得到参数,实际上看的是get和set方法是得到属性值的

@Param部分源码

在execute中方法中

 public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        Object param;
     //command.getType来判断方法类型是select delete insert  update
        switch(this.command.getType()) {
        case INSERT:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
            break;
        case UPDATE:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
            break;
        case DELETE:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
            break;
        case SELECT:
            if (this.method.returnsVoid() && this.method.hasResultHandler()) {
                this.executeWithResultHandler(sqlSession, args);
                result = null;
            } else if (this.method.returnsMany()) {
                result = this.executeForMany(sqlSession, args);
            } else if (this.method.returnsMap()) {
                result = this.executeForMap(sqlSession, args);
            } else if (this.method.returnsCursor()) {
                result = this.executeForCursor(sqlSession, args);
            } else {
                //来到这里  将方法参数转到sql语句参数  里面参数就是传的参数值  没有方法名
                param = this.method.convertArgsToSqlCommandParam(args);
                result = sqlSession.selectOne(this.command.getName(), param);
                if (this.method.returnsOptional() && (result == null || !this.method.getReturnType().equals(result.getClass()))) {
                    result = Optional.ofNullable(result);
                }
            }
            break;
        case FLUSH:
            result = sqlSession.flushStatements();
            break;
        default:
            throw new BindingException("Unknown execution method for: " + this.command.getName());
        }

        if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
            throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
        } else {
            return result;
        }
    }
 public Object getNamedParams(Object[] args) {
     //得到参数长度
        int paramCount = this.names.size();
        if (args != null && paramCount != 0) {
            if (!this.hasParamAnnotation && paramCount == 1) {
                Object value = args[(Integer)this.names.firstKey()];
                return wrapToMapIfCollection(value, this.useActualParamName ? (String)this.names.get(0) : null);
            } else {
                //
                Map<String, Object> param = new ParamMap();
                int i = 0;

                for(Iterator var5 = this.names.entrySet().iterator(); var5.hasNext(); ++i) {
                    Entry<Integer, String> entry = (Entry)var5.next();
                    //放入names  的entry集合的value  args得到真实参数
                    //(username admin) (password ,123456)
                    param.put(entry.getValue(), args[(Integer)entry.getKey()]);
                    //param1    param2
                    String genericParamName = "param" + (i + 1);
                    //如果names不含value  就以param1 param2为值
                    if (!this.names.containsValue(genericParamName)) {
                        //判断@param值本身是否是param1和 param2  如果是的话 就不放了
                      
                        param.put(genericParamName, args[(Integer)entry.getKey()]);
                    }
                }

                return param;
            }
        } else {
            return null;
        }
    }

后面执行这个方法来获取names

得到names

public ParamNameResolver(Configuration config, Method method) {
        this.useActualParamName = config.isUseActualParamName();
     //反射获得
        Class<?>[] paramTypes = method.getParameterTypes();
     //二维数组  参数有多个  一个参数对应多个注解
        Annotation[][] paramAnnotations = method.getParameterAnnotations();
        SortedMap<Integer, String> map = new TreeMap();
     //得到参数的个数
        int paramCount = paramAnnotations.length;
//对参数进行循环
        for(int paramIndex = 0; paramIndex < paramCount; ++paramIndex) {
            //判断类型是否是特殊的参数
            if (!isSpecialParameter(paramTypes[paramIndex])) {
                String name = null;
                //得到参数所有的注解循环
                Annotation[] var9 = paramAnnotations[paramIndex];
                int var10 = var9.length;

                for(int var11 = 0; var11 < var10; ++var11) {
                    Annotation annotation = var9[var11];
                    if (annotation instanceof Param) {
                        this.hasParamAnnotation = true;
                        //获取值
                        name = ((Param)annotation).value();
                        //检测到有注解  跳出当前循环
                        break;
                    }
                }

                if (name == null) {
                    if (this.useActualParamName) {
                        name = this.getActualParamName(method, paramIndex);
                    }

                    
                   
                    if (name == null) {
                        name = String.valueOf(map.size());
                    }
                }
                 //如果name不为空  放到map里面 以索引为键 值是@param的value值
                //第一次循环  放的是  (0,“username")
              //  第二次(1,“password”)
                map.put(paramIndex, name);
            }
        }
  //得到names
        this.names = Collections.unmodifiableSortedMap(map);
    }

回到上面那个函数

批量删除方式

只能使用${} 因为使用#{}会自动拼接字符串

  int deleteMore(String ids);

<delete id="deleteMore">
        delete from mybatis.t_user
        where id in (${ids})
    </delete>
    
        int i = mapper.deleteMore("1,2,5");

动态设置表名

在查询时如果select * from 表名 不固定式 需要传入参数

这是需要使用${}接受 因为在写sql语句是不需要对表名加单引号

添加功能获取自增主键

<insert id="insertUser" parameterType="User" useGeneratedKeys="true" keyProperty="id">
    insert  into t_user
    values (null,#{username},#{password},#{age},#{sex},#{email})
</insert>

void insertUser(User user);
useGeneratedKeys 设置当前标签中的sql使用了自增的主键

keyProperty:将自增的主键的值赋值给传输到映射文件参数的某个属性
自增主键的id会放在keyproperty里面

映射问题

多对一

多个员工对应一个部门

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Emp {
    private Integer eid;
    private String empName;
    private Integer age;
    private  String sex;
    private String email;
    private Integer did;

    private Dept dept;
}

//EmpMapper中的方法

   Emp getEmptAndDept(@Param("eid") Integer eid);

需要用resultMap做映射

  <resultMap id="EmpMap" type="Emp">
         <id column="eid" property="eid"></id>
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="sex" property="sex"></result>
        <result column="email" property="email"></result>
         <!-- 这里association的property的名字是 变量名  -->
        <association property="dept"   javaType="Dept">
             <id column="did" property="did"></id>
            <result column="dept_name" property="deptName"></result>
        </association>
    </resultMap>


     <select id="getEmptAndDept" resultMap="EmpMap">

         select *
       from mybatis.t_emp left join mybatis.t_dept
       on t_emp.did = t_dept.did
       where t_emp.eid=#{eid}
    </select>

一对多

一个部门对应多个员工

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Dept {
    private Integer did;
    private String deptName;

    private Emp emp;
}


//一般用Collection来接收
Collection<Dept>  getDept(Integer did);
<resultMap id="DeptMap" type="Dept">
        <id column="did" property="did"></id>
        <result column="dept_name" property="deptName"></result>

        <collection property="emp" ofType="Emp">
            <id column="eid" property="eid"></id>
            <result column="emp_name" property="empName"></result>
            <result column="age" property="age"></result>
            <result column="sex" property="sex"></result>
            <result column="email" property="email"></result>
            <result column="did" property="did"></result>
        </collection>
    </resultMap>

    <select id="getDept" resultMap="DeptMap">
                select * from mybatis.t_dept left join mybatis.t_emp
                on t_dept.did=t_emp.did
                where  t_dept.did=#{did}
    </select>

文章作者: 蛰伏
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 蛰伏 !
  目录