1. 程式人生 > 其它 >Mybatis全解-02

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執行流程

作用域理解

  • SqlSessionFactoryBuilder 的作用在於建立 SqlSessionFactory,建立成功後,SqlSessionFactoryBuilder 就失去了作用,所以它只能存在於建立 SqlSessionFactory 的方法中,而不要讓其長期存在。因此 SqlSessionFactoryBuilder 例項的最佳作用域是方法作用域(也就是區域性方法變數)。

  • SqlSessionFactory 可以被認為是一個數據庫連線池,它的作用是建立 SqlSession 介面物件。因為 MyBatis 的本質就是 Java 對資料庫的操作,所以 SqlSessionFactory 的生命週期存在於整個 MyBatis 的應用之中,所以一旦建立了 SqlSessionFactory,就要長期儲存它,直至不再使用 MyBatis 應用,所以可以認為 SqlSessionFactory 的生命週期就等同於 MyBatis 的應用週期。

  • 由於 SqlSessionFactory 是一個對資料庫的連線池,所以它佔據著資料庫的連線資源。如果建立多個 SqlSessionFactory,那麼就存在多個數據庫連線池,這樣不利於對資料庫資源的控制,也會導致資料庫連線資源被消耗光,出現系統宕機等情況,所以儘量避免發生這樣的情況。

  • 因此在一般的應用中我們往往希望 SqlSessionFactory 作為一個單例,讓它在應用中被共享。所以說 SqlSessionFactory 的最佳作用域是應用作用域。

  • 如果說 SqlSessionFactory 相當於資料庫連線池,那麼 SqlSession 就相當於一個數據庫連線(Connection 物件),你可以在一個事務裡面執行多條 SQL,然後通過它的 commit、rollback 等方法,提交或者回滾事務。所以它應該存活在一個業務請求中,處理完整個請求後,應該關閉這條連線,讓它歸還給 SqlSessionFactory,否則資料庫資源就很快被耗費精光,系統就會癱瘓,所以用 try...catch...finally... 語句來保證其正確關閉。

  • 所以 SqlSession 的最佳的作用域是請求或方法作用域。