别名
一般有两种方式设置别名
<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>