Mybatis全解-02
CRUD
查詢select
根據使用者id查詢對應的使用者
先編寫UserMapper介面
public interface UserMapper { //查詢全部使用者 List<User> selectUser(); //根據id查詢使用者 User selectUserById(int id); }
編寫完UserMapper介面後,就是編寫對應的UserMapper.xml檔案
id:對應接口裡的方法
resultType:返回值型別
裡面寫你需要的sql
<select id="selectUserById" resultType="com.li.pojo.User"> select * from user where id = #{id} </select>
在測試類中測試
@Test public void tsetSelectUserById() { SqlSession session = MybatisUtils.getSession(); //獲取SqlSession連線 UserMapper mapper = session.getMapper(UserMapper.class); User user = mapper.selectUserById(1); System.out.println(user); session.close(); }
根據使用者名稱和密碼查詢使用者
建議在介面方法的引數前加上@Param屬性,這樣的話,你在編寫sql的時候,直接取@Param中的值就可以了,不需要單獨設定引數的型別,避免了出現對映名字不同的問題。
//通過密碼和名字查詢使用者 User selectUserByNP(@Param("username") String username,@Param("pwd") Stringpwd); <select id="selectUserByNP" resultType="com.li.pojo.User"> select * from user where name = #{username} and pwd = #{pwd}</select>
思考:這裡只是根據使用者名稱和密碼兩個引數來查詢使用者,如果引數有很多個呢,那麼也需要一個一個加上引數嗎?
解決方法:使用Map進行引數傳遞。
首先在介面的方法中不要一個一個地加上引數,直接在裡面傳入Map。
User selectUserByNP2(Map<String,Object> map);
然後再將xml裡的引數型別設定為map。
parameterType="map"
<select id="selectUserByNP2" parameterType="map" resultType="com.li.pojo.User"> select * from user where name = #{username} and pwd = #{pwd} </select>
在使用的時候,把sql中的值作為map的key即可,最後直接將map放入方法中。
Map<String, Object> map = new HashMap<String, Object>(); map.put("username","小明"); map.put("pwd","123456"); User user = mapper.selectUserByNP2(map);
插入insert
//新增一個使用者 int addUser(User user);
<insert id="addUser" parameterType="com.li.pojo.User"> insert into user (id,name,pwd) values (#{id},#{name},#{pwd}) </insert>
@Test public void testAddUser() { SqlSession session = MybatisUtils.getSession(); UserMapper mapper = session.getMapper(UserMapper.class); User user = new User(5,"王五","zxcvbn"); int i = mapper.addUser(user); System.out.println(i); session.commit(); //提交事務,重點!不寫的話不會提交到資料庫 session.close(); }
千萬要注意:除了查詢,增刪改都要手動提交事務。
修改update
//修改一個使用者 int updateUser(User user);
<update id="updateUser" parameterType="com.li.pojo.User"> update user set name=#{name},pwd=#{pwd} where id = #{id} </update>
@Test public void testUpdateUser() { SqlSession session = MybatisUtils.getSession(); UserMapper mapper = session.getMapper(UserMapper.class); User user = mapper.selectUserById(1); user.setPwd("asdfgh"); int i = mapper.updateUser(user); System.out.println(i); session.commit(); //提交事務,重點!不寫的話不會提交到資料庫 session.close(); }
刪除delete
//根據id刪除使用者 int deleteUser(int id);
<delete id="deleteUser" parameterType="int"> delete from user where id = #{id} </delete>
@Test public void testDeleteUser() { SqlSession session = MybatisUtils.getSession(); UserMapper mapper = session.getMapper(UserMapper.class); int i = mapper.deleteUser(5); System.out.println(i); session.commit(); //提交事務,重點!不寫的話不會提交到資料庫 session.close(); }
注意點總結:
除了查詢,增刪改都需要手動提交事務。
Mapper介面中的所有普通引數,儘量都寫上@Param引數。
有時候考慮到業務需要,可以考慮使用map傳遞引數。
模糊查詢的兩種實現方法 關鍵詞:like
1.在sql語句中進行拼接,不建議使用這種,有可能引起sql注入問題。
string wildcardname = “smi”; list<name> names = mapper.selectlike(wildcardname); <select id=”selectlike”> select * from foo where bar like "%"#{value}"%" </select>
2.在java程式碼中新增sql萬用字元。
string wildcardname = “%smi%”; list<name> names = mapper.selectlike(wildcardname); <select id=”selectlike”> select * from foo where bar like #{value} </select>
mybatis核心配置檔案解析
configuration(配置) properties(屬性) settings(設定) typeAliases(類型別名) typeHandlers(型別處理器) objectFactory(物件工廠) plugins(外掛) environments(環境配置) environment(環境變數) transactionManager(事務管理器) dataSource(資料來源) databaseIdProvider(資料庫廠商標識) mappers(對映器) <!-- 注意元素節點的順序!順序不對會報錯 -->
注意:在配置的時候,需要注意裡面的順序,否則會報錯。
environments元素
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"> <property name="..." value="..."/> </transactionManager> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments>
後面是複數結尾,可知這是可以配置多套環境,通過default可指定預設使用環境。
有三種內建的資料來源型別:
type="[UNPOOLED|POOLED|JNDI]")
unpooled:每次被請求時開啟和關閉連線。
pooled:池的概念,一種快速響應請求的流行模式。
jndi:為了能夠在spring等容器中使用,容器集中或在外部配置資料來源,然後放置一個jdni上下文的引用。
當然,資料來源也有很多第三方的實現,在後面的框架整合中會用到。
Mappers
對映器:用來定義對映sql的xml檔案。
推薦使用兩種常用的:
1.使用相對於類路徑的資源引用 關鍵詞:resource,斜槓分隔,準確到xml檔案
<mappers> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers>
2.使用對映器介面實現類的完全限定類名,注意:xml檔名和mapper介面名稱一致,並且位於同一目錄下
<mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> </mappers>
mapper.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"> <mapper namespace="com.li.mapper.UserMapper"> </mapper>
namespace:名稱空間,繫結介面。繫結規則:包名+類名
優化問題
Properties優化
1.在資源目錄下新建一個db.properties檔案
driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf8 username=root password=123456
2.使用properties 屬性匯入配置檔案
<configuration> <!--匯入properties檔案--> <properties resource="db.properties"/> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers> </configuration>
typeAliases優化 關鍵字 alias
1.單個類設定別名
<typeAliases> <typeAlias type="com.li.pojo.User" alias="User"/> </typeAliases>
2.指定一個包名,所有的類別名都使用類首字母小寫
<typeAliases> <package name="com.li.pojo"/> </typeAliases>
3.使用註解
@Alias("user")
public class User {
...
}
這裡講的是常用的屬性,其他的相關屬性可以檢視官方文件。
作用域與生命週期的理解
Mybatis執行流程
作用域理解
-
-
SqlSessionFactory 可以被認為是一個數據庫連線池,它的作用是建立 SqlSession 介面物件。因為 MyBatis 的本質就是 Java 對資料庫的操作,所以 SqlSessionFactory 的生命週期存在於整個 MyBatis 的應用之中,所以一旦建立了 SqlSessionFactory,就要長期儲存它,直至不再使用 MyBatis 應用,所以可以認為 SqlSessionFactory 的生命週期就等同於 MyBatis 的應用週期。
-
由於 SqlSessionFactory 是一個對資料庫的連線池,所以它佔據著資料庫的連線資源。如果建立多個 SqlSessionFactory,那麼就存在多個數據庫連線池,這樣不利於對資料庫資源的控制,也會導致資料庫連線資源被消耗光,出現系統宕機等情況,所以儘量避免發生這樣的情況。
-
因此在一般的應用中我們往往希望 SqlSessionFactory 作為一個單例,讓它在應用中被共享。所以說 SqlSessionFactory 的最佳作用域是應用作用域。
-
如果說 SqlSessionFactory 相當於資料庫連線池,那麼 SqlSession 就相當於一個數據庫連線(Connection 物件),你可以在一個事務裡面執行多條 SQL,然後通過它的 commit、rollback 等方法,提交或者回滾事務。所以它應該存活在一個業務請求中,處理完整個請求後,應該關閉這條連線,讓它歸還給 SqlSessionFactory,否則資料庫資源就很快被耗費精光,系統就會癱瘓,所以用 try...catch...finally... 語句來保證其正確關閉。
-