本文将介紹簡單的select查詢
整個工程結構如下:
1. 需求,一個簡單的權限控制需求:使用者-角色-權限,表關系如下圖所示
- 建表語句
CREATE TABLE sys_user( id BIGINT AUTO_INCREMENT COMMENT '使用者ID', user_name VARCHAR() COMMENT '使用者名', user_password VARCHAR() COMMENT '密碼', user_email VARCHAR() COMMENT '郵箱', user_info TEXT COMMENT '簡介', head_img BLOB COMMENT '頭像', create_time DATETIME COMMENT '建立時間', PRIMARY KEY(id) )DEFAULT CHARSET=utf8; ALTER TABLE sys_user COMMENT '使用者表'; CREATE TABLE sys_role( id BIGINT AUTO_INCREMENT COMMENT '角色ID', role_name VARCHAR() COMMENT '角色名', enabled INT COMMENT '有效标志', create_by BIGINT COMMENT '建立人', create_time DATETIME COMMENT '建立時間', PRIMARY KEY(id) )DEFAULT CHARSET=utf8; ALTER TABLE sys_role COMMENT '角色表'; CREATE TABLE sys_privilege( id BIGINT AUTO_INCREMENT COMMENT '權限ID', privilege_name VARCHAR() COMMENT '權限名稱', privilege_url INT COMMENT '權限URL', PRIMARY KEY(id) )DEFAULT CHARSET=utf8; ALTER TABLE sys_role COMMENT '權限表'; CREATE TABLE sys_user_role( user_id BIGINT COMMENT '使用者ID', role_id BIGINT COMMENT '角色ID' )DEFAULT CHARSET=utf8; ALTER TABLE sys_user_role COMMENT '使用者角色關聯表'; CREATE TABLE sys_role_privilege( role_id BIGINT COMMENT '角色ID', privilege_id BIGINT COMMENT '權限ID' )DEFAULT CHARSET=utf8; ALTER TABLE sys_role_privilege COMMENT '角色權限關聯表'; insert into `sys_user` values('1','admin','123456','[email protected]','管理者',null,'2018-04-24 17:08:34'); insert into `sys_user` values('1001','test','123456','[email protected]','測試使用者',null,'2018-04-24 17:08:34'); insert into `sys_role` values('1','管理者','1','1','2018-04-24 14:34:34'); INSERT INTO `sys_role` VALUES('2','普通使用者','1','1','2018-04-24 15:08:34'); insert into `sys_user_role` values('1','1'); insert into `sys_user_role` values('1','2'); insert into `sys_user_role` values('1001','2'); insert into `sys_privilege` values('1','使用者管理','/users'); insert into `sys_privilege` values('2','角色管理','/roles'); insert into `sys_privilege` values('3','系統日志','/logs'); insert into `sys_privilege` values('4','人員維護','/persons'); insert into `sys_privilege` values('5','機關維護','/companies'); insert into `sys_role_privilege` values('1','1'); insert into `sys_role_privilege` values('1','3'); insert into `sys_role_privilege` values('1','2'); insert into `sys_role_privilege` values('2','4'); insert into `sys_role_privilege` values('2','5'); #添加外鍵限制 ALTER TABLE sys_user_role ADD FOREIGN KEY(user_id) REFERENCES sys_user(id) ; ALTER TABLE sys_user_role ADD FOREIGN KEY(role_id) REFERENCES sys_role(id) ; ALTER TABLE sys_role_privilege ADD FOREIGN KEY(role_id) REFERENCES sys_role(id) ; ALTER TABLE sys_role_privilege ADD FOREIGN KEY(privilege_id) REFERENCES sys_privilege(id) ;
-
實體類建立
SysUser、SysRole、Sysprivilege、SysUserRole、SysRolePrivilege代碼如下:
package tk.mybatis.simple.model; import java.util.Date; /** * 使用者表 * 命名方式:下劃線轉駝峰 * 具體采用什麼方式不重要, * 可以通過resultMap對資料庫的列和類的字段配置映射關系 */ public class SysUser { /** * 使用者ID * 由于java中的基本類型有預設值,例如當某個類中存在 private int age 字段時, * 建立這個類時,age會有預設值0,當使用age屬性時,它總會有值。是以在某些情況下, * 便無法實作使age為null。并且在動态SQL的部分,如果使用age!=null進行判斷, * 結果總會為true,因而會導緻很多隐藏的問題 * * 是以,在實體類中不要使用基本資料類型 */ private Long id; /** * 使用者名 */ private String userName; /** * 使用者密碼 */ private String userPassword; /** * 使用者郵箱 */ private String userEmail; /** * 簡介 */ private String userInfo; /** * 頭像 * 在MyBatis中, 關于資料庫字元按和java類型的對應關系,不需要可以去記, * 但是需要注意一個特殊類型 "byte[]",這個類型一般對應資料庫中的BLOB、 * LONGVARBINARY以及一些和二進制流有關的字段類型。 */ private Byte[] headImg; /** * 建立時間 */ private Date createTime; //省去了get和set方法 }
public class SysRole { private Long id; private String roleName; private Integer enabled; private Long creatBy; private Date createTime; //省去了get和set方法 }
public class Sysprivilege { /** * 權限ID */ private Long id; /** * 權限名稱 */ private String privilegeName; /** * 權限URL */ private String privilegeUrl; //省去了get和set方法 }
/** * 使用者角色表 */ public class SysUserRole { /** * 使用者ID */ private Long userId; /** * 角色ID */ private Long roleId; //省去了get和set方法 }
public class SysRolePrivilege { private Long roleId; private Long privilegeId; //省去了get和set方法 }
-
xml配置方式
在src/main/resources目錄下的tk/mybatis/simple/mapper目錄下 建立UserMapper.xml,RoleMapper.xml,PrivilegeMapper.xml,UserRoleMapper.xml,RolePrivilegeMapper.xml。
然後再src/main/java目錄下的tk.mybatis.simple.mapper包下面建立UserMapper.java, RoleMapper.java,PrivilegeMapper.java,UserRoleMapper.java,RolePrivilegeMapper.java
這裡僅僅以UserMapper.xml和UserMapper.java為例說明:
UserMapper.xml
再在mybatis-config.xml檔案中引入這五個XML配置檔案 (這種配置比較繁瑣,因為每次添加新的配置檔案,都要重新在這裡添加可以配置成掃描包的方式)<?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"> <!-- 注意:namespace屬性 當xml檔案和接口關聯的時候,namespace屬性必須寫接口的全限定名 mybatis内部就是通過這個namespace屬性将兩者關聯起來的 映射XML和接口的命名需要符合如下規則: 1. 當隻使用XML而不使用接口的時候,namespace的值可以設定為任意不重複的名稱 2. 标簽id屬性值在任何時候都不能出現英文句号".",并且同一個命名空間下不能出現重複的id 3. 因為接口中方法可以重載,是以接口中可以出現多個同名不同參數的方法,但是XML中的id不能重複 因而接口中的所有的同名方法會對應着XML中的同一個id的方法。 最常見的用法就是:同名方法中其中一個方法增傑一個RowBunds類型的參數用于實作分頁查詢 --> <mapper namespace="tk.mybatis.simple.mapper.UserMapper"> </mapper>
替代上面的配置如下:(兩個方式可以共存)<mappers> <mapper resource="tk/mybatis/simple/mapper/CountryMapper.xml"/> <mapper resource="tk/mybatis/simple/mapper/UserMapper.xml"/> <mapper resource="tk/mybatis/simple/mapper/RoleMapper.xml"/> <mapper resource="tk/mybatis/simple/mapper/PrivilegeMapper.xml"/> <mapper resource="tk/mybatis/simple/mapper/UserRoleMapper.xml"/> <mapper resource="tk/mybatis/simple/mapper/RolePrivilegeMapper.xml"/> </mappers>
<mappers> <mapper resource="tk/mybatis/simple/mapper/CountryMapper.xml"/> <package name="tk.mybatis.simple.mapper"/> </mappers>
配置為掃描包的方式添加mapper.xml配置檔案,循環對接口進行如下操作 判斷接口對應的命名空間是否已經存在,如果存在就抛出異常, 不存在就繼續進行接下來的操作 加載接口對應的XML映射檔案,将接口全限定名轉換為路徑,例如: 将接口tk.mybatis.simple.mapper.UserMapper 轉換為 tk/mybatis/simple/mapper/UserMapper.xml,以.xml為字尾搜尋 XML資源,如果找到就解析XML 處理接口中的注解方法 因為這裡的接口和XML映射檔案完全符合上面操作的第點,是以直接配置包名就能 自動掃描包下的接口和XML映射檔案,省去了很多麻煩
- select的用法一
UserMapper.xml配置檔案中添加如下配置:/** * 通過id查詢使用者 * 該傳回值類型必須和配置檔案中的傳回值類型一緻,否則報錯 * @param id * @return */ SysUser selectById(Long id); /** * 查詢全部使用者 * @return */ List<SysUser> selectAll();
第二個select語句,也可以開啟駝峰映射,在mybatis-config.xml檔案中配置如下:<!-- resultMap:用于配置java對象的屬性和查詢列的對應關系,必須熟練掌握 标簽id:必填,唯一 type: 必填,用于配置java對象的屬性和查詢列的對應關系 另外兩個沒有寫的屬性: extends="" :選填,可以配置目前resultMap繼承自其他的resultMap,屬性值為繼承resultMap的id autoMapping="":選填,可選值為true或false,用于配置是否啟動非映射字段(沒有在resultMap中配置的字段) 的自動映射功能,該配置可以覆寫全局的autoMappingBehavior配置 --> <resultMap id="userMap" type="tk.mybatis.simple.model.SysUser" autoMapping="false"> <!-- <constructor> <idArg></idArg> <arg ></arg> </constructor> constructor标簽:配置使用構造方法注入結果,包含idArg和arg兩個标簽 idArg:id參數,标記結果作為id(唯一值),可以幫助提高整體性能 arg:注入到構造方法的一個普通結果 --> <!-- id參數,代表的主鍵值(唯一值) column:從資料庫中得到的列名,或者是列的别名 property:映射到列結果的屬性,可以映射簡單的,如"username"這樣的屬性 也可以映射複雜的屬性,例如"address.street.number", 通過"."的方式的屬性嵌套指派 javaType:一個java類的全限定名,或者一個類型别名 如果映射到JavaBean,MyBatis通常可以自動判斷屬性類型 如果映射到HashMap,則需要明确指定javaType屬性 jdbcType:列對應的資料庫類型(針對插入,更新,删除操作可能為空的列進行) 這是JDBC jdbcType的需要,而不是MyBatis的需要 --> <id property="id" column="id"/> <result property="userName" column="user_name"/> <result property="userPassword" column="user_password"/> <result property="userEmail" column="user_email"/> <result property="headImg" column="head_img" jdbcType="BLOB"/> <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> </resultMap> <!-- selectById:通過id查詢使用者 select:映射查詢語句使用的标簽, 此處的id必須和接口中方法的名字一樣 如果接口方法沒有和XML中的id屬性值對應,程式啟動便會報錯。 resultMap:是上面定義的resultMap标簽裡面的id屬性值,通過id引用需要的resultMap /* 查詢語句 #{id}:MyBatis SQL中使用的預編譯參數的一種方式,id是傳入的參數名 */ --> <select id="selectById" resultMap="userMap"> SELECT * FROM sys_user WHERE id = #{id} </select> <!-- 這裡通過設定别名的方式來和java屬性值比對 實際上:别名的大小寫和實際java屬性的大小寫并不敏感 因為Mybatis會将兩者都轉換成大寫做比較 但是書寫還是要規範 --> <select id="selectAll" resultType="tk.mybatis.simple.model.SysUser"> SELECT id, user_name userName, user_password userPassword, user_email userEmai, user_info userInfo, head_Img headImg, create_time createTime FROM sys_user </select>
這樣第二個select語句可以寫為如下格式:<settings> <!-- 開啟駝峰映射 --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
<select id="selectAll" resultType="tk.mybatis.simple.model.SysUser"> SELECT id, user_name, user_password, user_email, user_info, head_Img, create_time FROM sys_user </select>
-
- 測試代碼:
修改CountryMapperTest為如下代碼:package tk.mybatis.simple.mapper; 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; import java.io.IOException; import java.io.InputStream; import java.io.Reader; /** * 基礎測試類 * @author snow */ public class BaseMapperTest { private static SqlSessionFactory sqlSessionFactory; @BeforeClass public static void init(){ try { InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } public SqlSession getSqlSession(){ return sqlSessionFactory.openSession(); } }
package tk.mybatis.simple.mapper; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import tk.mybatis.simple.model.Country; import java.util.List; /** * @author snow */ public class CountryMapperTest extends BaseMapperTest{ @Test public void testSelect(){ //建立session SqlSession sqlSession = getSqlSession(); System.out.println(sqlSession); try { List<Country> countryList = sqlSession.selectList("tk.mybatis.simple.mapper.CountryMapper.selectAll"); printCountryList(countryList); }finally { //千萬不要忘記關閉sqlSession sqlSession.close(); } } private static void printCountryList(List<Country> countrylist){ countrylist.forEach((country)->{ System.out.printf("%-4d%4s%4s\n",country.getId(),country.getCountryname(),country.getCountrycode()); }); } } /*--------------------------------------------------------------------------- 測試結果: [DEBUG] 2018-04-25 21:27:56,538 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ==> Preparing: SELECT id, countryname, countrycode from country [DEBUG] 2018-04-25 21:27:56,614 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ==> Parameters: [TRACE] 2018-04-25 21:27:56,666 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Columns: id, countryname, countrycode [TRACE] 2018-04-25 21:27:56,667 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Row: 1, 中國, CN [TRACE] 2018-04-25 21:27:56,669 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Row: 2, 美國, US [TRACE] 2018-04-25 21:27:56,669 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Row: 3, 俄羅斯, RU [TRACE] 2018-04-25 21:27:56,670 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Row: 4, 英國, GB [TRACE] 2018-04-25 21:27:56,670 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Row: 5, 法國, FR [DEBUG] 2018-04-25 21:27:56,670 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) <== Total: 5 1 中國 CN 2 美國 US 3 俄羅斯 RU 4 英國 GB 5 法國 FR ----------------------------------------------------------------------------------*/
package tk.mybatis.simple.mapper; import org.apache.ibatis.session.SqlSession; import org.junit.Assert; import org.junit.Test; import tk.mybatis.simple.model.SysRole; import tk.mybatis.simple.model.SysUser; import java.util.List; import static org.junit.Assert.*; public class UserMapperTest extends BaseMapperTest{ @Test public void testSelectById() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); SysUser sysUser = userMapper.selectById(L); //sysUser不為空 Assert.assertNotNull(sysUser); //使用者名為admin Assert.assertEquals("admin",sysUser.getUserName()); }finally { sqlSession.close(); } } /*---------------------------------------------------------------------------------- 測試結果: [DEBUG] 2018-04-25 21:30:03,057 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ==> Preparing: SELECT * FROM sys_user WHERE id = ? [DEBUG] 2018-04-25 21:30:03,107 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ==> Parameters: 1(Long) [TRACE] 2018-04-25 21:30:03,153 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time [TRACE] 2018-04-25 21:30:03,153 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Row: 1, admin, 123456, [email protected], <<BLOB>>, <<BLOB>>, 2018-04-24 17:08:34.0 [DEBUG] 2018-04-25 21:30:03,159 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) <== Total: 1 ----------------------------------------------------------------------------------*/ @Test public void testSelectAll() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<SysUser> list = userMapper.selectAll(); //sysUser不為空 Assert.assertNotNull(list); //使用者名為admin Assert.assertTrue(list.size()>); }finally { sqlSession.close(); } } } /*---------------------------------------------------------------------------------- 測試結果: [DEBUG] 2018-04-25 21:30:55,468 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ==> Preparing: SELECT id, user_name userName, user_password userPassword, user_email userEmai, user_info userInfo, head_Img headImg, create_time createTime FROM sys_user [DEBUG] 2018-04-25 21:30:55,524 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ==> Parameters: [TRACE] 2018-04-25 21:30:55,894 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Columns: id, userName, userPassword, userEmai, userInfo, headImg, createTime [TRACE] 2018-04-25 21:30:55,896 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Row: 1, admin, 123456, [email protected], <<BLOB>>, <<BLOB>>, 2018-04-24 17:08:34.0 [TRACE] 2018-04-25 21:30:55,905 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Row: 1001, test, 123456, [email protected], <<BLOB>>, <<BLOB>>, 2018-04-24 17:08:34.0 [DEBUG] 2018-04-25 21:30:55,908 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) <== Total: 2 ----------------------------------------------------------------------------------*/
-
select用法二(複雜查詢:根據使用者id來擷取對應的角色資訊,要求查詢出來角色的同時,将使用者的使用者名和郵箱查詢出來)
SysRole.java修改如下:
UserMapper.java裡面添加如下方法:/** * 增加一個字段,提供set和get方法 */ private SysUser user;
/** * 根據使用者id來擷取對應的角色資訊 * @param id * @return */ List<SysRole> selectRolesByUserId(Long id);
UserMapper.xml添加如下配置:
需要注意的是:這裡通過user.userName就可以給實體類SysRole裡面的user屬性的userName屬性指派成功
測試方法代碼添加如下:<select id="selectRolesByUserId" resultType="tk.mybatis.simple.model.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>
@Test public void testSelectRolesByUserId() { SqlSession sqlSession = getSqlSession(); try { UserMapper userMapper = sqlSession.getMapper(UserMapper.class); List<SysRole> list = userMapper.selectRolesByUserId(L); //sysUser不為空 Assert.assertNotNull(list); //使用者名為admin Assert.assertTrue(list.size()>); }finally { sqlSession.close(); } } /*---------------------------------------------------------------------------------- [DEBUG] 2018-04-25 22:00:12,678 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ==> Preparing: 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 = ? [DEBUG] 2018-04-25 22:00:12,742 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ==> Parameters: 1(Long) [TRACE] 2018-04-25 22:00:12,811 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Columns: id, roleName, enabled, createBy, createTime, user.userName, user.userEmail [TRACE] 2018-04-25 22:00:12,812 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Row: 1, 管理者, 1, 1, 2018-04-24 14:34:34.0, admin, [email protected] [TRACE] 2018-04-25 22:00:12,812 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.trace(BaseJdbcLogger.java:165) <== Row: 2, 普通使用者, 1, 1, 2018-04-24 15:08:34.0, admin, [email protected] [DEBUG] 2018-04-25 22:00:12,812 method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) <== Total: 2 ----------------------------------------------------------------------------------*/