<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
1、介面的方法可以進行過載,因為 java 語法可以讓介面函數進行過載。
1、結論:可以有條件的進行過載。
2、為什麼會有這個問題?:mybatis裡面將介面裡面的方法名稱和組態檔裡面的id屬性進行唯一配對,在同一個名稱空間下只能有一個id,那麼所有函數名稱相同的過載函數都會被繫結到一個id上,所以,如果要實現函數的過載,必須讓一個SQL語句去適應多個函數的引數,如果是單純的過載是肯定不行的(過載函數的定義就是引數相關),但是得益於mybatis的多種傳參方式和隱性的分頁功能,可以在介面裡面進行函數過載,但是還是需要將所有的過載函數適配到同一個id的SQL上面去,仍然有很大的侷限性,並不是可以隨意的進行過載。
1、資料庫環境
DROP TABLE IF EXISTS sys_user; CREATE TABLE sys_user( id BIGINT NOT NULL AUTO_INCREMENT COMMENT '使用者的ID', user_name VARCHAR(50) COMMENT '使用者名稱稱', user_password VARCHAR(50) COMMENT '密碼', user_email VARCHAR(50) COMMENT '郵箱', user_info TEXT COMMENT '簡介', head_img BLOB COMMENT '頭像', create_time DATETIME COMMENT '建立時間', PRIMARY KEY (id) )DEFAULT CHARSET utf8; ALTER TABLE sys_user COMMENT '使用者表'; INSERT INTO sys_user VALUES ('1','admin','123456','admin@mybatis.tk','管理員',null,'2016-04-01 17:00:58'); INSERT INTO sys_user VALUES ('1001','test','123456','test@mybatis.tk','測試使用者',null,'2016-04-01 17:01:52');
2、實體類
public class SysUser { private Long id; private String userName; private String userPassword; private String userEmail; private String userInfo; private byte[] headImg; private Date createTime; public SysUser(){ } /**setter and getter*/ }
3、測試
3.1、測試模板程式碼
public class SysUserDaoTest { private static SqlSessionFactory sqlSessionFactory; private SqlSession sqlSession; @BeforeClass public static void beforeClass(){ String resource = "plus/mybatis-config.xml"; try{ InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); }catch(IOException e){ e.printStackTrace(); } } @Before public void before(){ //事物手動提交 sqlSession = sqlSessionFactory.openSession(false); } @After public void after(){ //回滾事物 sqlSession.rollback(true); //關閉對談 sqlSession.close(); } }
3.2、測試場景一
過載實現分頁、引數型別轉換實現過載。
3.2.1、介面
public interface SysUserDao { SysUser selectById(Long id); List<SysUser> selectById(Long id,RowBounds rowBound); }
3.2.2、mapper組態檔
<!-- id:注意事項:介面方法不能進行過載,在3.4版本後是錯的!!!!!,因為至少可以分頁!!! 1、介面中的所有過載方法對應XML裡面的同一個ID,但是3.4之後有一個分頁的外掛,所以至少可以接受一個org.apache.ibatis.session.RowBounds的隱性引數。 2、雖然介面裡面的方法可以進行過載,但是需要一個前提:不要指定 parameterType 屬性!! 介面方法如下: SysUser selectById(Long id); List<SysUser> selectById(Long id,RowBounds rowBound); SysUser selectById(String name); 測試程式碼如下: SysUserDao sysUserDao = sqlSession.getMapper(SysUserDao.class); SysUser sysUser = sysUserDao.selectById(1L); Assert.assertEquals("admin",sysUser.getUserName()); SysUser sysUser1 = sysUserDao.selectById("1"); Assert.assertEquals("admin",sysUser1.getUserName()); /* plus.dao.SysUserDao.selectById - ==> Preparing: SELECT * FROM sys_user WHERE id = ?; plus.dao.SysUserDao.selectById - ==> Parameters: 1(Long) plus.dao.SysUserDao.selectById - <== Total: 1 plus.dao.SysUserDao.selectById - ==> Preparing: SELECT * FROM sys_user WHERE id = ?; plus.dao.SysUserDao.selectById - ==> Parameters: 1(String) plus.dao.SysUserDao.selectById - <== Total: 1 */ RowBounds rowBound = new RowBounds(0,2); List<SysUser> sysUsers = sysUserDao.selectById(1L,rowBound); Assert.assertEquals(1,sysUsers.size()); /* plus.dao.SysUserDao.selectById - ==> Preparing: SELECT * FROM sys_user WHERE id = ?; plus.dao.SysUserDao.selectById - ==> Parameters: 1(Long) plus.dao.SysUserDao.selectById - <== Total: 1 */ 事實證明,當不指定引數型別的時候(也僅僅當不指定引數型別的時候才可以,因為過載過載的是引數),是可以進行 介面方法過載的,因為mybatis的引數型別推斷會自動的轉換引數型別,比如: sysUserDao.selectById("楚雲飛"); 因為ID的型別是Long型別,所以資料型別的自動轉換失敗,但是是不會出現異常的,只是它選取出來的資料集為null,因為ID的型別是bigint,沒有bigint值為楚雲飛,所以為null結果集。 --> <select id="selectById" resultMap="sysUser" flushCache="true"> SELECT * FROM sys_user WHERE id = #{id}; </select> <resultMap id="sysUser" type="plus.pojo.SysUser"> <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="userInfo" column="user_info"/> <result property="headImg" column="head_img" jdbcType="BLOB"/> <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> </resultMap>
3.3、測試場景二
引數傳遞方式實現過載,map引數傳遞和固定引數名的引數傳遞方式
3.3.1、介面
public interface SysUserDao { SysUser selectByCondition(@Param("id")Long id,@Param("userName")String userName,@Param("userPassword")String userPassword); SysUser selectByCondition(Map params); }
3.3.2、mapper組態檔
<!-- 固定引數傳遞: 函數介面: SysUser selectByCondition(@Param("id")Long id,@Param("userName")String userName,@Param("userPassword")String userPassword); SysUser selectByCondition(Map params); 測試函數: @Test public void selectByCondition(){ SysUserDao sysUserDao = sqlSession.getMapper(SysUserDao.class); SysUser sysUser = sysUserDao.selectByCondition(1L,"admin","123456"); Assert.assertEquals("admin@mybatis.tk",sysUser.getUserEmail()); /* plus.dao.SysUserDao.selectByCondition - ==> Preparing: SELECT * FROM sys_user WHERE id = ? AND user_name = ? AND user_password = ?; plus.dao.SysUserDao.selectByCondition - ==> Parameters: 1(Long), admin(String), 123456(String) plus.dao.SysUserDao.selectByCondition - <== Total: 1 */ Map<String,Object> params = new HashMap<String,Object>(3); //傳入的鍵值必須和SQL語句裡面的以及過載函數的引數名稱相同才可以實現正確的過載,否則將過載出錯。 params.put("id",1L); params.put("userName","admin"); params.put("userPassword","123456"); SysUser sysUser1 = sysUserDao.selectByCondition(params); /* plus.dao.SysUserDao.selectByCondition - ==> Preparing: SELECT * FROM sys_user WHERE id = ? AND user_name = ? AND user_password = ?; plus.dao.SysUserDao.selectByCondition - ==> Parameters: 1(Long), admin(String), 123456(String) plus.dao.SysUserDao.selectByCondition - <== Total: 1 */ Assert.assertEquals("admin@mybatis.tk",sysUser1.getUserEmail()); } --> <select id="selectByCondition" resultMap="sysUser" flushCache="true"> SELECT * FROM sys_user WHERE id = #{id} AND user_name = #{userName} AND user_password = #{userPassword}; </select>
3.4、完整的測試程式碼
package plus.dao; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.*; import org.junit.*; import plus.pojo.SysUser; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Map; public class SysUserDaoTest { private static SqlSessionFactory sqlSessionFactory; private SqlSession sqlSession; @BeforeClass public static void beforeClass(){ String resource = "plus/mybatis-config.xml"; try{ InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); }catch(IOException e){ e.printStackTrace(); } } @Before public void before(){ //事物手動提交 sqlSession = sqlSessionFactory.openSession(false); } @After public void after(){ //回滾事物 sqlSession.rollback(true); //關閉對談 sqlSession.close(); } @Test public void selectById(){ SysUserDao sysUserDao = sqlSession.getMapper(SysUserDao.class); SysUser sysUser = sysUserDao.selectById(1L); Assert.assertEquals("admin",sysUser.getUserName()); SysUser sysUser1 = sysUserDao.selectById("1"); Assert.assertEquals("admin",sysUser1.getUserName()); /* plus.dao.SysUserDao.selectById - ==> Preparing: SELECT * FROM sys_user WHERE id = ?; plus.dao.SysUserDao.selectById - ==> Parameters: 1(Long) plus.dao.SysUserDao.selectById - <== Total: 1 plus.dao.SysUserDao.selectById - ==> Preparing: SELECT * FROM sys_user WHERE id = ?; plus.dao.SysUserDao.selectById - ==> Parameters: 1(String) plus.dao.SysUserDao.selectById - <== Total: 1 */ RowBounds rowBound = new RowBounds(0,2); List<SysUser> sysUsers = sysUserDao.selectById(1L,rowBound); Assert.assertEquals(1,sysUsers.size()); /* plus.dao.SysUserDao.selectById - ==> Preparing: SELECT * FROM sys_user WHERE id = ?; plus.dao.SysUserDao.selectById - ==> Parameters: 1(Long) plus.dao.SysUserDao.selectById - <== Total: 1 */ } @Test public void selectByCondition(){ SysUserDao sysUserDao = sqlSession.getMapper(SysUserDao.class); SysUser sysUser = sysUserDao.selectByCondition(1L,"admin","123456"); Assert.assertEquals("admin@mybatis.tk",sysUser.getUserEmail()); /* plus.dao.SysUserDao.selectByCondition - ==> Preparing: SELECT * FROM sys_user WHERE id = ? AND user_name = ? AND user_password = ?; plus.dao.SysUserDao.selectByCondition - ==> Parameters: 1(Long), admin(String), 123456(String) plus.dao.SysUserDao.selectByCondition - <== Total: 1 */ Map<String,Object> params = new HashMap<String,Object>(3); params.put("id",1L); params.put("userName","admin"); params.put("userPassword","123456"); SysUser sysUser1 = sysUserDao.selectByCondition(params); /* plus.dao.SysUserDao.selectById - ==> Preparing: SELECT * FROM sys_user WHERE id = ?; plus.dao.SysUserDao.selectById - ==> Parameters: 1(Long) plus.dao.SysUserDao.selectById - <== Total: 1 */ Assert.assertEquals("admin@mybatis.tk",sysUser1.getUserEmail()); } }
3.5、完整的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="plus.dao.SysUserDao"> <!-- id:當使用介面時,屬性值必須為介面裡面的方法名稱,在同一個名稱空間裡面不重複,否則將啟動報錯; 在任何情況下,id屬性不能出現英文句點 '.' (Caused by: org.apache.ibatis.builder.BuilderException: Dots are not allowed in element names, please remove it) ; 注意事項:介面方法不能進行過載,在3.4版本後是錯的!!!!!,因為可以分頁!!! 1、介面中的所有過載方法對應XML裡面的同一個ID,但是3.4之後有一個分頁的外掛,所以可以接受一個org.apache.ibatis.session.RowBounds的隱性引數。 2、雖然介面裡面的方法可以進行過載,但是如果要在執行的時候依然不報錯的話,需要一個前提:不要指定 parameterType 屬性!! 介面方法如下: SysUser selectById(Long id); List<SysUser> selectById(Long id,RowBounds rowBound); SysUser selectById(String name); 測試程式碼如下: SysUserDao sysUserDao = sqlSession.getMapper(SysUserDao.class); SysUser sysUser = sysUserDao.selectById(1L); Assert.assertEquals("admin",sysUser.getUserName()); SysUser sysUser1 = sysUserDao.selectById("1"); Assert.assertEquals("admin",sysUser1.getUserName()); /* plus.dao.SysUserDao.selectById - ==> Preparing: SELECT * FROM sys_user WHERE id = ?; plus.dao.SysUserDao.selectById - ==> Parameters: 1(Long) plus.dao.SysUserDao.selectById - <== Total: 1 plus.dao.SysUserDao.selectById - ==> Preparing: SELECT * FROM sys_user WHERE id = ?; plus.dao.SysUserDao.selectById - ==> Parameters: 1(String) plus.dao.SysUserDao.selectById - <== Total: 1 */ RowBounds rowBound = new RowBounds(0,2); List<SysUser> sysUsers = sysUserDao.selectById(1L,rowBound); Assert.assertEquals(1,sysUsers.size()); /* plus.dao.SysUserDao.selectById - ==> Preparing: SELECT * FROM sys_user WHERE id = ?; plus.dao.SysUserDao.selectById - ==> Parameters: 1(Long) plus.dao.SysUserDao.selectById - <== Total: 1 */ 事實證明,當不指定引數型別的時候(也僅僅當不指定引數型別的時候才可以,因為過載過載的是引數),是可以進行 介面方法過載的,因為mybatis的引數型別推斷會自動的轉換引數型別,比如: sysUserDao.selectById("楚雲飛"); 因為ID的型別是Long型別,所以資料型別的自動轉換失敗,但是是不會出現異常的,只是它選取出來的資料集為null --> <select id="selectById" resultMap="sysUser" flushCache="true"> SELECT * FROM sys_user WHERE id = #{_parameter}; </select> <!-- 引數傳遞問題: 1、介面函數: SysUser selectByCondition(Long id,String userName,String userPassword); 引數傳遞: 1、預設引數傳遞:預設的引數的命名為 param + 序位,SQL語句如下: SELECT * FROM sys_user WHERE id = #{param1} AND user_name = #{param2} AND user_password = #{param3}; 2、預設引數傳遞:直接序列引數,SQL語句如下: SELECT * FROM sys_user WHERE id = #{0} AND user_name = #{1} AND user_password = #{2}; 3、固定引數傳遞: 函數介面: SysUser selectByCondition(@Param("id")Long id,@Param("userName")String userName,@Param("userPassword")String userPassword); SQL語句如下: SELECT * FROM sys_user WHERE id = #{id} AND user_name = #{userName} AND user_password = #{userPassword}; 4、使用Map傳遞引數: 函數介面:SysUser selectByCondition(Map params); 呼叫程式碼段: Map<String,Object> params = new HashMap<String,Object>(3); params.put("id",1L); params.put("userName","admin"); params.put("userPassword","123456"); SysUser sysUser1 = sysUserDao.selectByCondition(params); Assert.assertEquals("admin@mybatis.tk",sysUser1.getUserEmail()); SQL語句: SELECT * FROM sys_user WHERE id = #{id} AND user_name = #{userName} AND user_password = #{userPassword}; 思考: 1、與固定引數的SQL相比,沒有改變SQL語句,而且兩個介面實現過載。 2、介面函數可以實現過載,但是需要SQL語句來相容這個函數的過載,也就是可以進行有條件的過載。 5、使用 $ 和 # 進行取值的區別: 1. #將傳入的資料都當成一個字串,會對自動傳入的資料加一個雙引號。如:order by #user_id#,如果傳入的值是111,那麼解析成sql時的值為order by "111", 如果傳入的值是id,則解析成的sql為order by "id". 2. $將傳入的資料直接顯示生成在sql中。如:order by $user_id$,如果傳入的值是111,那麼解析成sql時的值為order by user_id, 如果傳入的值是id,則解析成的sql為order by id. 3. #方式能夠很大程度防止sql注入。 4.$方式無法防止Sql注入。 5.$方式一般用於傳入資料庫物件,例如傳入表名. 6.一般能用#的就別用$. SELECT * FROM sys_user WHERE id = ${id} AND user_name = '${userName}' AND user_password = '${userPassword}'; --> <select id="selectByCondition" resultMap="sysUser" flushCache="true"> SELECT * FROM sys_user WHERE id = #{id} AND user_name = #{userName} AND user_password = #{userPassword}; </select> <resultMap id="sysUser" type="plus.pojo.SysUser"> <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="userInfo" column="user_info"/> <result property="headImg" column="head_img" jdbcType="BLOB"/> <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/> </resultMap> </mapper>
3.6、完整的介面
public interface SysUserDao { SysUser selectById(Long id); List<SysUser> selectById(Long id,RowBounds rowBound); SysUser selectById(String name); SysUser selectByCondition(@Param("id")Long id,@Param("userName")String userName,@Param("userPassword")String userPassword); SysUser selectByCondition(Map params); }
利用介面預設方法 default 實現
利用動態sql對 userId 欄位進行判斷
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45