目录
1、特殊SQL的执行
1.1、模胡查询
/**
* 通过用户名模胡查询用户信息
* @param mohu
* @return
*/
List<User> getUserByLike(@Param("mohu")String mohu);
<!-- List<User> getUserByLike(@Param("mohu")String mohu);-->
<!-- select * from t_user where username like '%${mohu}%';-->
<!-- select * from t_user where username like concat('%',#{mohu},'%');-->
<select id="getUserByLike" resultType="user">
select * from t_user where username like "%"#{mohu}"%";
</select>
测试
@Test
public void testGetUserByLike(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
List<User> a = mapper.getUserByLike("a");
System.out.println(a);
}
测试结果
DEBUG 08-26 17:49:40,116==> Preparing: select * from t_user where username like "%"?"%"; (BaseJdbcLogger.java:137)
DEBUG 08-26 17:49:40,132==> Parameters: a(String) (BaseJdbcLogger.java:137)
DEBUG 08-26 17:49:40,148<== Total: 7 (BaseJdbcLogger.java:137)
[User{id=2, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'},
User{id=5, username='a', password='111', age=11, gender='男', email='123466@qq.com'},
User{id=9, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'},
User{id=10, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'},
User{id=11, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'},
User{id=12, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'},
User{id=13, username='admin', password='123456', age=23, gender='男', email='123456@qq你.com'}]
1.2、批量删除
/**
* 批量删除
* @param ids
*/
void deleteMoreUser(@Param("ids") String ids);
<!-- void deleteMoreUser(@Param("ids") String ids);-->
<delete id="deleteMoreUser">
delete from t_user where id in(${ids});
</delete>
测试
@Test
public void testDeleteMoreUser(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
mapper.deleteMoreUser("7,6");
}
1.3、动态设置表名
/**
* 动态设置表名,查询用户信息
* @param tableName
* @return
*/
List<User> getUserList(@Param("tableName") String tableName);
<!-- List<User> getUserList(@Param("tableName") String tableName);-->
<select id="getUserList" resultType="user">
select * from ${tableName};
</select>
测试
@Test
public void testGetUserList(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
List<User> t_user = mapper.getUserList("t_user");
t_user.forEach(new Consumer<User>() {
@Override
public void accept(User user) {
System.out.println(user.toString());
}
});
}
1.4、添加功能获取自增主键
场景模拟:
t_clazz(clazz_id,clazz_name)
t_student(student_id,student_name,clazz_id)
1、添加班级信息
2、获取新添加的班级的id
3、为班级分配学生,即将某学的班级id修改为新添加的班级的id
/**
* 添加用户信息并获取自增的主键
* @param user
*/
void insertUser(User user);
<!-- void insertUser(User user);-->
<!--
useGeneratedKeys:表示当前添加功能使用自增的主键
keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中
-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user values(null,#{username},#{password},#{age},#{gender},#{email});
</insert>
测试
@Test
public void testInsertUser(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
SpecialSQLMapper mapper = sqlSession.getMapper(SpecialSQLMapper.class);
User user = new User(null,"小红","123456",23,"男","23930@qq.com");
mapper.insertUser(user);
System.out.println(user);
}
DEBUG 08-26 17:55:20,653==> Preparing: insert into t_user values(null,?,?,?,?,?); (BaseJdbcLogger.java:137)
DEBUG 08-26 17:55:20,668==> Parameters: 小红(String), 123456(String), 23(Integer), 男(String), 23930@qq.com(String) (BaseJdbcLogger.java:137)
DEBUG 08-26 17:55:20,700<== Updates: 1 (BaseJdbcLogger.java:137)
User{id=19, username='小红', password='123456', age=23, gender='男', email='23930@qq.com'}
开始时,传入的User的id为空,在执行插入方法后,User的id会被赋值,从而得到自增的主键
2、自定义映射resultMap
前期准备:
t_dept表(部门表)
create table t_dept
(
dept_id int auto_increment primary key,
dept_name varchar(20) null
);
t_emp表(员工表,部门对员工,一对多,一个部门对应多个员工)
create table t_emp
(
emp_id int auto_increment primary key,
emp_name varchar(20) null,
age int null,
gender char null,
dept_id int null
);
实体类
Dept类
public class Dept {
private Integer deptId;
private String deptName;
private List<Emp> emps;
public Dept() {
}
public Dept(Integer deptId, String deptName) {
this.deptId = deptId;
this.deptName = deptName;
}
public Integer getDeptId() {
return deptId;
}
public void setDeptId(Integer deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public List<Emp> getEmps() {
return emps;
}
public void setEmps(List<Emp> emps) {
this.emps = emps;
}
@Override
public String toString() {
return "Dept{" +
"deptId=" + deptId +
", deptName='" + deptName + '\'' +
", emps=" + emps +
'}';
}
}
Emp类
public class Emp {
private Integer empId;
private String empName;
private Integer age;
private String gender;
private Dept dept;
public Emp() {
}
public Emp(Integer empId, String empName, Integer age, String gender) {
this.empId = empId;
this.empName = empName;
this.age = age;
this.gender = gender;
}
public Emp(Integer empId, String empName, Integer age, String gender, Dept dept) {
this.empId = empId;
this.empName = empName;
this.age = age;
this.gender = gender;
this.dept = dept;
}
public Dept getDept() {
return dept;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Emp{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", dept=" + dept +
'}';
}
}
SqlSessionUtil工具类
public class SqlSessionUtil {
public static SqlSession getSqlSession(){
SqlSession sqlSession =null;
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
sqlSession = sqlSessionFactory.openSession(true);
} catch (IOException e) {
e.printStackTrace();
}
return sqlSession;
}
}
2.1、resultMap处理资源和属性的映射关系
字段名和属性名不一致的情况,如何处理映射关系
1、为查询的字段设置别名,和属性名保持一致
2、当字段符合MySql的要求使用,而属性符合java的要求使用驼峰
此时可以在MyBatis的核心配置文件中设置一个全局配置mapUnderscoreToCamelCase,可以自动将下划线映射为驼峰。例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为 userName
<settings>
<!-- 将下划线映射为驼峰-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
3.使用resultMap自定义映射处理
resultMap:设置自定义的映射关系
id:唯一标识
type:处理映射关系的实体类的类型
常用标签
id:处理主键和实体类中属性的映射关系
result:处理普通字段和实体类中的属性的映射关系
association:处理多对一的映射关系(处理实体类类型的属性)
column:设置映射关系中的字段名,必须是sql查询出的某个字段
property:设置映射关系中的属性的属性名,必须是处理实体类类型中的属性名
/**
* 根据id查询员工信息
* @param empId
* @return
*/
Emp getEmpById(@Param("empId") Integer empId);
<resultMap id="empResultMap" type="Emp">
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
</resultMap>
<!-- Emp getEmpById(@Param("empId") Integer empId);-->
<select id="getEmpById" resultMap="empResultMap">
select * from t_emp where emp_id = #{empId};
</select>
2.2、多对一映射处理
场景模拟:
查询员工信息以及员工所对应的部门信息
2.2.1、级联方式处理映射关系
/**
* 查询员工信息以及员工所对应的部门信息
* @param empId
* @return
*/
Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);
<resultMap id="empAndDeptResultMapOne" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<result column="dept_id" property="dept.deptId"></result>
<result column="dept_name" property="dept.deptName"></result>
</resultMap>
<!-- Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMapOne">
select
t_emp.*,t_dept.*
from
t_emp
left join
t_dept
on t_emp.dept_id = t_dept.dept_id
where t_emp.emp_id = #{empId};
</select>
2.2.2、使用association处理映射关系
/**
* 查询员工信息以及员工所对应的部门信息
* @param empId
* @return
*/
Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);
<resultMap id="empAndDeptResultMap" type="emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!--
association:处理多对一的映射关系(处理实体类类型的属性)
property:设置需要处理映射关系的属性的属性名
javaType:设置要处理的属性的类型
-->
<association property="dept" javaType="Dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
</association>
</resultMap>
<!-- Emp getEmpAndDeptByEmpId(@Param("empId") Integer empId);-->
<select id="getEmpAndDeptByEmpId" resultMap="empAndDeptResultMap">
select
t_emp.*,t_dept.*
from
t_emp
left join
t_dept
on t_emp.dept_id = t_dept.dept_id
where t_emp.emp_id = #{empId};
</select>
2.2.3、分步查询
1、查询与员工信息
/**
* 查询员工以及对应的部门信息的第一步
* @param empId
* @return
*/
Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);
<!-- Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);-->
<resultMap id="empAndDeptByStepResultMap" type="Emp">
<id column="emp_id" property="empId"></id>
<result column="emp_name" property="empName"></result>
<result column="age" property="age"></result>
<result column="gender" property="gender"></result>
<!--
property:设置需要处理映射关系的属性的属性名
select:设置分步查询的sql的唯一标识
column:将查询出的某个字段作为分步查询的sql的条件
fetchType:在开启了延迟加载的环境中,通过该属性设置当前的分步查询是否使用延迟加载
fetchType="eager(立即加载)| lazy(延迟加载)"
-->
<association property="dept" fetchType="eager"
select="com.itwpf.mapper.DeptMapper.getEmpAndDeptByStepTwo"
column="dept_id">
</association>
</resultMap>
<select id="getEmpAndDeptByStepOne" resultMap="empAndDeptByStepResultMap">
select * from t_emp where emp_id = #{empId};
</select>
2.根据员工信息所对应的部门id查询部门信息
/**
* 查询员工以及对应的部门信息的第二步
* @return
*/
Dept getEmpAndDeptByStepTwo(@Param("deptId")Integer deptId);
<!-- Dept getEmpAndDeptByStepTwo(@Param("deptId")Integer deptId);-->
<select id="getEmpAndDeptByStepTwo" resultType="dept">
select * from t_dept where dept_id = #{deptId};
</select>
2.3、一对多映射处理
2.3.1、collection
/**
* 查询部门以及部门的员工信息
* @param deptId
* @return
*/
Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);
<resultMap id="getDeptAndEmpResultMap" type="dept">
<id column="dept_id" property="deptId"></id>
<result column="dept_name" property="deptName"></result>
<collection property="emps" ofType="emp">
<!-- ofType:设置集合类型属性中存储的数据的类型-->
<id column="emp_id" property="empId"/>
<result column="emp_name" property="empName"/>
<result column="age" property="age"/>
<result column="gender" property="gender"/>
</collection>
</resultMap>
<!-- Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);-->
<select id="getDeptAndEmpByDeptId" resultMap="getDeptAndEmpResultMap">
select t_dept.*,t_emp.*
from t_dept
left join t_emp
on t_dept.dept_id = t_emp.dept_id
where t_dept.dept_id = #{deptId};
</select>
2.3.2、分步查询
1、查询部门信息
/**
* 通过分步查询部门以及部门中员工信息的第一步
* @param deptId
* @return
*/
Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);
<resultMap id="deptAndEmpResultMapByStep" type="dept">
<id column="dept_id" property="deptId"/>
<result column="dept_name" property="deptName"/>
<collection property="emps"
select="com.itwpf.mapper.EmpMapper.getDeptAndEmpByStepTwo"
column="dept_id"/>
</resultMap>
<!-- Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);-->
<select id="getDeptAndEmpByStepOne" resultMap="deptAndEmpResultMapByStep">
select *
from t_dept
where dept_id = #{deptId};
</select>
2.根据部门id查询部门中的所有员工
/**
*通过分步查询部门以及部门中员工信息的第二步
* @param deptId
* @return
*/
List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);
<!-- List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);-->
<select id="getDeptAndEmpByStepTwo" resultType="emp">
select * from t_emp where dept_id = #{deptId};
</select>
分步查询的优点:可以实现延迟加载 但是必须在核心配置文件中设置全局配置信息:
<settings>
<!-- 开启延时加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 按需加载 如果为true,不管有没有开启延时加载,都会执行全部sql-->
<!-- <setting name="aggressiveLazyLoading" value="false"/>-->
</settings>
lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载
aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属 性会按需加载 此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。
此时可通过association和 collection中的fetchType属性设置当前的分步查询是否使用延迟加载, fetchType="lazy(延迟加 载)|eager(立即加载)"