04.SSM框架集~Mybatis(二)
本文是上一篇文章的後續,詳情點擊該鏈接
在上一篇文章中,我們簡單介紹了一下Mybatis,和Mybatis的最基本使用。那麼今天我們就來學習一下Mybatis基於代理模式的開發和動態SQL
Mapper代理:
前面已經使用Mybatis完成了對Student表的最基本操作,實現了MyBatis的入門。
但是卻存在如下缺點:
1:不管是selectList()、selectOne()、selectMap(),都是通過SQLSession對象的API完成增刪改查,都只能提供一個查詢參數。如果要多個參數,需要封裝到JavaBean或者Map中,並不一定永遠是一個好辦法。
2:返回值類型較固定
3:只提供了映射文件,沒有提供數據庫操作的接口,不利於後期的維護擴展。在MyBatis中提供了另外一種成爲Mapper代理(或稱爲接口綁定)的操作方式。在實際開發中也使用該方式。
下面我們就是要Mapper代理的方式來實現對Student表的CRUD操作吧。相比而言,增加了接口StudentMapper。但是卻會引起映射文件和測試類的變化。
首先我們回到mybatis.xml,修改配置
<mappers>
<!-- 通過包掃描的形式加載所有的接口和映射文件 -->
<package name="com.alvin.mapper"/>
</mappers>
這樣一來,不管將來新增了多少個mapper映射文件,只要都在這個包下,就無需重複去寫
(關於SqlSessionUtil類以及一些配置和jar包,詳情請點擊最上方鏈接,看我上一篇文章的內容。)
優點:
有接口 模塊之間有規範了
參數的處理多樣了,接口中的方法參數列表由我們自己決定
通過代理模式由mybatis提供接口的實現類對象 我們不用寫實現類了
使用Mapper代理方式實現查詢
需求:查詢全部學生信息
準備接口和mapper映射文件
public interface StudentMapper {
//查詢全部學生信息
List<Student> FindAll();
}
<?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="com.alvin.mapper.StudentMapper">
<!-- 這裏的id必須和對應的方法名相同 -->
<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());
}
}
}
關於Mapper代理的增刪查改操作
創建好接口:
public interface StudentMapper {
//查詢全部學生信息
List<Student> FindAll();
//增加學生信息
int Insert(Student student);
//刪除學生信息
int delete(String son);
//修改學生信息
int change(Student student);
//查詢單個學生信息
Student FindByOn(String son);
}
Mapper映射
<?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="com.alvin.mapper.StudentMapper">
<!-- 這裏的id必須和對應的方法名相同 -->
<select id="FindAll" resultType="student">
select * from student;
</select>
<!-- 增,刪,改 返回值默認爲int,所以這裏就沒有resultType參數 -->
<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>
Java代碼
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);
Mapper映射
<!-- 模糊查詢 -->
<select id="getByName" resultType="student" >
select * from student where realname like concat('%',#{realname},'%')
</select>
Java代碼
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
動態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語句,可讀性很差,所以較少使用。
Where和IF標籤
通過if處理用戶多變的查詢條件
接口
public interface StudentMapper {
//登錄實現
Student Login(Student student);
}
Mapper映射
<?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="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>
Java代碼
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);
}
Choose When標籤
在剛剛的標籤裏面進行修改
<?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="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就不再判斷了
Set標籤
修改案例
接口
int update(Student student);
Mapper映射
<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>
Java
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();
}
Trim標籤
處理set
<update id="update" >
<!--prefix 要增加什麼前綴
prefixOverrides 要去除什麼前綴
suffix 要增加什麼後綴
suffixOverrides 要去除什麼後綴
set 和where是 trim的一種特殊情況
-->
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>
處理where
<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>
Sql片段標籤
案例: 根據指定字段查詢
接口
List<Student> FindAll();
Mapper
<!-- 將字段包含 -->
<sql id="data">
son,realname,password,classname,score
</sql>
<!-- 調用 -->
<select id="FindAll" resultType="student">
select <include refid="data"/> from student;
</select>
Java
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());
}
}
好了!今天我們就學到這裏吧,我們下期再見~