在上一篇文章中,我们简单介绍了一下Mybatis,和Mybatis的最基本使用。那么今天我们就来学习一下Mybatis基于代理模式的开发和动态SQL
前面已经使用Mybatis完成了对Student表的最基本操作,实现了MyBatis的入门。
但是却存在如下缺点:
1:不管是selectList()、selectOne()、selectMap(),都是通过SQLSession对象的API完成增删改查,都只能提供一个查询参数。如果要多个参数,需要封装到JavaBean或者Map中,并不一定永远是一个好办法。
2:返回值类型较固定
3:只提供了映射文件,没有提供数据库操作的接口,不利于后期的维护扩展。在MyBatis中提供了另外一种成为Mapper代理(或称为接口绑定)的操作方式。在实际开发中也使用该方式。
下面我们就是要Mapper代理的方式来实现对Student表的CRUD操作吧。相比而言,增加了接口StudentMapper。但是却会引起映射文件和测试类的变化。
<mappers>
<!-- 通过包扫描的形式加载所有的接口和映射文件 -->
<package name="com.alvin.mapper"/>
</mappers>
这样一来,不管将来新增了多少个mapper映射文件,只要都在这个包下,就无需重复去写
(关于SqlSessionUtil类以及一些配置和jar包,详情请点击最上方链接,看我上一篇文章的内容。)
有接口 模块之间有规范了
参数的处理多样了,接口中的方法参数列表由我们自己决定
通过代理模式由mybatis提供接口的实现类对象 我们不用写实现类了
需求:查询全部学生信息
public interface StudentMapper {
//查询全部学生信息
List<Student> FindAll();
}
<mapper namespace="com.alvin.mapper.StudentMapper">
<select id="FindAll" resultType="student">
select * from student;
select>
mapper>
接口的名字必须和映射文件名字相同!
public class Test {
public static void main(String[] args){
//查询全部学生信息
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
// 帮助我们生成一个接口下的实现类对象的
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
// 接收数据
List<Student> list = studentMapper.FindAll();
//关闭sqlSession
sqlSession.close();
//遍历结果
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
public interface StudentMapper {
//查询全部学生信息
List<Student> FindAll();
//增加学生信息
int Insert(Student student);
//删除学生信息
int delete(String son);
//修改学生信息
int change(Student student);
//查询单个学生信息
Student FindByOn(String son);
}
<mapper namespace="com.alvin.mapper.StudentMapper">
<select id="FindAll" resultType="student">
select * from student;
select>
<insert id="Insert">
insert into student value(#{son},#{realname},#{password},#{classname},#{score});
insert>
<update id="change">
update student set realname = #{realname}, password = #{password},classname = #{classname},score = #{score} where son = #{son};
update>
<delete id="delete">
delete from student where son = #{son}
delete>
<select id="FindByOn" resultType="student">
select * from student where son = #{son};
select>
mapper>
public class Test {
public static void main(String[] args){
//Insert();
// Del();
//FindAll();
//Update();
Find();
}
//查询全部学生信息
public static void FindAll(){
//查询全部学生信息
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
// 帮助我们生成一个接口下的实现类对象的
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
// 接收数据
List<Student> list = studentMapper.FindAll();
//关闭sqlSession
sqlSession.close();
//遍历结果
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
//新增学生信息
public static void Insert(){
//当执行增删改时,就需要提交True,否则无法完成操作!
SqlSession sqlSession = SqlSessionUtil.getSqlSession(true);
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
//需要新增的信息
Student student = new Student("666666","黄贵根","666666","信息工程学院",533.0);
//调用新增
int n = studentMapper.Insert(student);
//关闭sqlSession
sqlSession.close();
//处理结果
String str = n > 0 ? "新增成功!" : "新增失败!";
System.out.println(str);
}
//修改学生信息
public static void Update(){
//当执行增删改时,就需要提交True,否则无法完成操作!
SqlSession sqlSession = SqlSessionUtil.getSqlSession(true);
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
//需要修改的信息
Student student = new Student("666666","黄贵根","123456","信息工程学院",600.0);
//调用修改
int n = studentMapper.change(student);
//关闭sqlSession
sqlSession.close();
//处理结果
String str = n > 0 ? "修改成功!" : "修改失败!";
System.out.println(str);
}
//删除学生信息
public static void Del(){
//当执行增删改时,就需要提交True,否则无法完成操作!
SqlSession sqlSession = SqlSessionUtil.getSqlSession(true);
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
//调用删除
int n = studentMapper.delete("666666");
//关闭sqlSession
sqlSession.close();
//处理结果
String str = n > 0 ? "删除成功!" : "删除失败!";
System.out.println(str);
}
//查找学生信息
public static void Find(){
//查询操作则无需提交
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
//调用查询
Student student = studentMapper.FindByOn("154787");
//关闭sqlSession
sqlSession.close();
//处理结果
String str = student != null ? student.toString() : "没找到!";
System.out.println(str);
}
}
//模糊查询
List<Student> getByName( String realname);
<select id="getByName" resultType="student" >
select * from student where realname like concat('%',#{realname},'%')
select>
public static void main(String[] args) {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
//查询姓名包含张的学生
List<Student> students = mapper.getByName("张");
//遍历
Iterator iterator = students.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
sqlSession.close();
}
好了,关于Mapper代理这一块的基本知识,暂时先学到这里,现在让我们来了解一下动态SQL
经常遇到很多按照很多查询条件进行查询的情况,比如智联招聘的职位搜索,比如OA系统中的支出查询等。其中经常出现很多条件不取值的情况,在后台应该如何完成最终的SQL语句呢?
如果采用JDBC进行处理,需要根据条件是否取值进行SQL语句的拼接,一般情况下是使用StringBuilder类及其append方法实现,还是有些繁琐的。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
MyBatis在简化操作方法提出了动态SQL功能,将使用Java代码拼接SQL语句,改变为在XML映射文件中截止标签拼接SQL语句。相比而言,大大减少了代码量,更灵活、高度可配置、利于后期维护。
MyBatis中动态SQL是编写在mapper.xml中的,其语法和JSTL类似,但是却是基于强大的OGNL表达式实现的。
MyBatis也可以在注解中配置SQL,但是由于注解功能受限,尤其是对于复杂的SQL语句,可读性很差,所以较少使用。
通过if处理用户多变的查询条件
public interface StudentMapper {
//登录实现
Student Login(Student student);
}
<mapper namespace="com.alvin.mapper.StudentMapper">
<select id="Login" resultType="student">
select * from student
<where>
<if test="son != null">
and son= #{son}
if>
<if test="realname != null and realname != ''">
and realname= #{realname}
if>
<if test="password != null and password != ''">
and password = #{password}
if>
<if test="classname != null ">
and classname = #{classname}
if>
<if test="score != null ">
and score = #{score}
if>
where>
select>
mapper>
public static void Login(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = new Student();
//输入账号和密码
student.setSon("666666");
student.setPassword("666666");
Student stu = mapper.Login(student);
//处理结果
String string = stu != null ? "登陆成功!欢迎您: " + stu.getRealname() : "登陆失败!";
System.out.println(string);
}
在刚刚的标签里面进行修改
<mapper namespace="com.alvin.mapper.StudentMapper">
<select id="Login" resultType="student">
select * from student
<where>
<choose>
<when test="son != null">
and son= #{son}
when>
<when test="realname != null and realname != ''">
and realname= #{realname}
when>
<when test="password != null and password != ''">
and password = #{password}
when>
<when test="classname != null ">
and classname = #{classname}
when>
<when test="score != null ">
and score = #{score}
when>
choose>
where>
select>
mapper>
特点:前面的when条件成立 后面的 when就不再判断了
修改案例
int update(Student student);
<update id="update" >
update student
<set>
<if test="realname != null and realname != ''">
realname= #{realname},
if>
<if test="password != null and password != ''">
password = #{password},
if>
<if test="classname != null ">
classname = #{classname},
if>
<if test="score != null ">
score = #{score},
if>
set>
where son = #{son}
update>
public static void Update(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession(true);
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
Student student = new Student();
//修改后的数据
Student stu = new Student("666666","黄贵根","654321","信息工程学院",666.0);
int n = mapper.update(stu);
//处理结果
String string = n > 0 ? "修改成功!" : "修改失败!";
System.out.println(string);
//关闭
sqlSession.close();
}
处理set
<update id="update" >
update student
<trim prefix="set" suffixOverrides=",">
<if test="realname != null and realname != ''">
realname= #{realname},
if>
<if test="password != null and password != ''">
password = #{password},
if>
<if test="classname != null ">
classname = #{classname},
if>
<if test="score != null ">
score = #{score},
if>
trim>
where son = #{son}
update>
<select id="Login" resultType="student">
select * from student
<trim prefix="where" prefixOverrides="and">
<if test="son != null">
and son= #{son}
if>
<if test="realname != null and realname != ''">
and realname= #{realname}
if>
<if test="password != null and password != ''">
and password = #{password}
if>
<if test="classname != null ">
and classname = #{classname}
if>
<if test="score != null ">
and score = #{score}
if>
trim>
select>
案例: 根据指定字段查询
List<Student> FindAll();
<sql id="data">
son,realname,password,classname,score
sql>
<select id="FindAll" resultType="student">
select <include refid="data"/> from student;
select>
public static void main(String[] args) {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
List<Student> list = studentMapper.FindAll();
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
好了!今天我们就学到这里吧,我们下期再见~