在上一篇博客中,我們初識了Mybatis,瞭解了怎樣使用Mybatis來對數據庫進行操作,在本篇博客中,我們將實現單個參數的增刪改查功能,分別瞭解select,insert,update,delete的基本用法。
一.創建數據庫表與實體類
在很多系統中都需要權限管理,因此我們在這裏對權限管理進行需求分析,建立其數據庫表和對應的實體類。在數據庫中我們建立了用戶表sys_user,角色表sys_role,權限表sys_privilege,用戶角色關聯表sys_user_role,角色權限關聯表sys_role_privilege。這五個表結構如下所示。建好五個表之後,在tk.mybatis.sample.model中創建對應的實體類,如何建立實體類在上篇博客中學習,在這裏不在贅述。
二.創建xml文件和接口類,配置mybatis
首先根據數據庫中的五個表在src/main/resources中tk.mybatis.sample.mapper下創建對應的xml文件分別是UserMapper.xml,RoleMapper.xml,PrivilegeMapper.xml,UserRoleMapper.xml,RolePrivilegeMapper.xml,然後在src/main/java中創建包tk.mybatis.sample.mapper創建對應的接口類,類名同xml文件。創建xml文件在上一篇博客中也有敘述。創建完畢後在mybatis-config.xml配置文件中配置所有mapper文件。
<mappers>
<mapper resource="tk/mybatis/sample/mapper/UserMapper.xml"/>
<mapper resource="tk/mybatis/sample/mapper/RoleMapper.xml"/>
<mapper resource="tk/mybatis/sample/mapper/PrivilegeMapper.xml"/>
<mapper resource="tk/mybatis/sample/mapper/UserRoleMapper.xml"/>
<mapper resource="tk/mybatis/sample/mapper/RolePrivilegeMapper.xml"/>
</mappers>
但是這種配置方式需要將所有映射文件都列舉出來,如果增加了新的映射文件還需要記得添加,操作起來比較麻煩,所有在這裏我們採用另外一種配置方式如下:
<mappers>
<package name="tk.mybatis.sample.mapper" />
</mappers>
這種配置方式會查找tk.mybatis.sample.mapper包下所有的接口,加載接口對應的xml映射文件。
三.SELECT基本用法
在很多時候我們需要查詢系統中的用戶、角色、權限等數據,這就需要寫查詢語句。先寫一個根據用戶ID查詢用戶信息的方法,首先我們在UserMapper接口類中添加一個selectById方法
/**
* 通過ID查詢用戶
*
* @param ID
* @return
*
*/
SysUser selectById(Long id);
然後在對應的UserMapper.xml文件中添加<resultMap>和<select>部分的代碼
<?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="tk.mybatis.sample.mapper.UserMapper">
<resultMap id="userMap" type="tk.mybatis.sample.model.SysUser">
<result property="id" column="id"></result>
<result property="userName" column="user_name"></result>
<result property="userPassword" column="user_password"></result>
<result property="userEmail" column="user_email"></result>
<result property="userInfo" column="user_info"></result>
<result property="headImg" column="head_img"></result>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"></result>
</resultMap>
<select id="selectById" resultMap="userMap">
select * from sys_user where id = #{id}
</select>
</mapper>
可以發現,在接口中的方法名和xml文件中select的id屬性是一樣的,在Mybatis中就是通過這種方式將接口方法和xml的sql語句關聯在一起的,所以在xml文件中不能出現重複的id屬性值。而在select中的#{id}則是Mybatis中使用預編譯參數的一種方式,大括號中的內容就是傳入的參數名。resultMap是用於設置返回值的類型和映射關係的,如果在select中不使用配置的resultmap而是使用resultType,那麼需要在sql語句中爲所有列名和屬性名不一致的列設置別名,從而實現自動映射(在接下來的方法中可以看到)。
接下來我們添加一個selectAll的方法。
/**
* 查詢全部用戶
*
* @return
*/
List<SysUser> selectAll();
同樣的,我們在UserMapper.xml文件中添加對應的select,這裏使用的返回值就是resultType,可以看到將表中列名重命名成爲SysUser類中屬性名。
<select id="selectAll" resultType="SysUser">
select id,
user_name userName,
user_password userPassword,
user_email userEmail,
user_info userInfo,
head_img headImg,
create_time createTime
from sys_user
</select>
而如果我們需要通過用戶ID返回對應的角色信息,同時需要返回一部分的用戶信息,那該怎麼辦呢?在這裏我們添加這樣一個方法selectRoleByUserId。
/**
* 根據用戶ID獲取角色信息
*
* @param userId
* @return
*/
List<SysRole> selectRoleByUserId(Long userId);
接着在xml文件中添加相應的select語句。這裏有兩種簡單方法設置其返回值,一是在SysRole對象中直接添加我們需要的屬性(例如直接添加userName和userEmail屬性)或是在SysRole中直接添加SysUser對象,這裏我們使用的是第二種。
<select id="selectRoleByUserId" resultType="SysRole">
select
r.id,
r.role_name roleName,
r.enabled,
r.create_by createBy,
r.create_time createTime,
u.user_name as "user.userName",
u.user_email as "user.userEmail"
from sys_user u
inner join sys_user_role ur on u.id = ur.user_id
inner join sys_role r on ur.role_id = r.id
where u.id = #{userId}
</select>
四.INSERT基本用法
我們在UserMapper中添加一個增加新用戶的方法insert。
/**
* 增加新用戶
*
* @param SysUser
* @return
*/
int insert(SysUser sysUser);
同時在xml文件中添加對應的對應代碼。在該insert中,可以看到爲headImg和createTime兩個參數配置了jdbcType屬性,這是爲了防止出現類型錯誤。同時在insert中我們配置了useGeneratedKeys和keyProperty兩個屬性,配置這兩個屬性之後,Mybatis會使用jdbc的方法提取數據庫內部的主鍵,將其賦值給keyProperty配置的id屬性(當有多個屬性時,要使用逗號隔開,同時要設置keyColumn屬性)。還有一種selectKey方法可以返回主鍵值,大家感興趣可以去搜索學習。
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
insert into sys_user(id,user_name,user_password,user_email,
user_info,head_img,create_time)
values(
#{id},#{userName},#{userPassword},#{userEmail},
#{userInfo},#{headImg, jdbcType=BLOB},
#{createTime, jdbcType=TIMESTAMP})
</insert>
五.UPDATE基本用法
首先我們添加一個根據主鍵更新數據的方法updateById。
/**
* 根據主鍵更新
*
* @param sysUser
* @return
*/
int updateById(SysUser sysUser);
在xml中添加對應的<update>。在這裏只介紹最基本的update用法,複雜的情況將在之後介紹。
<update id="updateById">
update sys_user
set user_name = #{userName},
user_password = #{userPassword},
user_email = #{userEmail},
user_info = #{userInfo},
head_img = #{headImg, jdbcType=BLOB},
create_time = #{createTime, jdbcType=TIMESTAMP}
where id = #{id}
</update>
六.DELETE基本用法
delete和update用法基本類似,以一個簡單的例子說明。我們添加一個方法deleteById。
/**
* 根據主鍵刪除
*
* @param ID
* @return
*/
int deleteById(Long id);
接着添加相應的代碼到xml文件中。
<delete id="deleteById">
delete from sys_user where id = #{id}
</delete>
七.編寫測試基類
由於以後我們需要更多的測試類,所以在這裏創建一個測試基類BaseMapperTest,將所有測試類中通用的部分添加進去。
/*
* 基礎測試類
* */
package tk.mybatis.sample.mapper;
import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.BeforeClass;
public class BaseMapperTest {
private static SqlSessionFactory sqlSessionFactory;
@BeforeClass
public static void init(){
try{
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
reader.close();
} catch (IOException e){
e.printStackTrace();
}
}
public SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
八.測試結果及項目結構
我們將根據從上之下的順序將本篇文章中介紹的所有方法的測試方法及其結果展示出來。
- selectById
@Test
public void testSelectById(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
SysUser user = usermapper.selectById(1l);
//Assert.assertNotNull(user);
//Assert.assertEquals("admin", user.getUserName());
} finally{
sqlSession.close();
}
}
- selectAll
@Test
public void testSelectAll(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
List<SysUser> userList = usermapper.selectAll();
//Assert.assertNotNull(userList);
//Assert.assertTrue(userList.size()>0);
} finally{
sqlSession.close();
}
}
- selectRoleByUserId
@Test
public void testSelectRoleByUserId(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
List<SysRole> roleList = usermapper.selectRoleByUserId(1l);
//Assert.assertNotNull(userList);
//Assert.assertTrue(userList.size()>0);
} finally{
sqlSession.close();
}
}
- insert
@Test
public void testInsert(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
SysUser user = new SysUser();
user.setUserName("test1");
user.setUserPassword("123456");
user.setUserEmail("[email protected]");
user.setUserInfo("test info");
user.setHeadImg(new byte[]{1,2,3});
user.setCreateTime(new Date());
int result = usermapper.insert(user);
System.out.println(user.getId());
} finally{
sqlSession.commit();
sqlSession.close();
}
}
- testUpdateById
@Test
public void testUpdateById(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
SysUser user = usermapper.selectById(1l);
user.setUserName("admin_test");
user.setUserEmail("[email protected]");
int result = usermapper.updateById(user);
user = usermapper.selectById(1l);
} finally{
sqlSession.rollback();
sqlSession.close();
}
}
- deleteById
@Test
public void testDeleteById(){
SqlSession sqlSession = getSqlSession();
try{
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
SysUser user1 = usermapper.selectById(1l);
int result = usermapper.deleteById(1l);
SysUser user2 = usermapper.selectById(1l);
} finally{
sqlSession.rollback();
sqlSession.close();
}
}
在這裏值得一提的是,在執行update,insert,delete三個操作時,需要對sqlSession進行commit操作,否則這三個操作將不會影響到數據庫,因爲sqlSessionFactory.openSession()是不自動提交的,在測試中,我們爲了不影響其他測試的結果,所以選擇進行操作回滾。
整個項目結構如下所示:
上一篇:Mybatis學習日記(一)——初識Mybatis,一個簡單demo
下一篇:Mybatis學習日記(三)——使用@param方法傳遞多個參數