您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關Mybatis怎么用,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
1、Mybatis概述
MyBatis 是支持普通 SQL 查詢(相比較于Hibernate的封裝,Mybatis是半自動化的JDBC封裝,一個特點就是Mybatis執行的SQL查詢語句需要自己在配置文件中寫),存儲過程和高級映射的優秀持久層框架。MyBatis 消除了幾乎所有的 JDBC 代碼和參數的手工設置以及對結果集的檢索。MyBatis 可以使用簡單的XML 或注解用于配置和原始映射,將接口和 Java 的 POJO(Plain Old Java Objects,普通的Java 對象)映射成數據庫中的記錄。
2、Mybatis原理解析
下面以Mybatis簡單的執行流程
1、加載mybatis全局配置文件(數據源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成Configuration,和一個個MappedStatement(包括了參數映射配置、動態SQL語句、結果映射配置),其對應著<select | update | delete | insert>標簽項。
2、SqlSessionFactoryBuilder通過Configuration對象生成SqlSessionFactory,用來開啟SqlSession。
3、SqlSession對象完成和數據庫的交互:
a、用戶程序調用mybatis接口層api(即Mapper接口中的方法)
b、SqlSession通過調用api的Statement ID找到對應的MappedStatement對象
c、通過Executor(負責動態SQL的生成和查詢緩存的維護)將MappedStatement對象進行解析,sql參數轉化、動態sql拼接,生成jdbc Statement對象
d、JDBC執行sql。
e、借助MappedStatement中的結果映射關系,將返回結果轉化成HashMap、JavaBean等存儲結構并返回。
下面是Mybatis的框架原理圖
3、Mybatis簡單實例
(1)導入相關jar包以及Mybatis運行環境核心jar包和連接數據庫的包
(2)創建一張簡單的數據表
(3)創建Java對象(PO類型)
package cn.mybatis.po; public class User { private int id; private String username; private String password; private String address; private String sex; public int getId() { return id; } public String getUsername() { return username; } public String getPassword() { return password; } public String getAddress() { return address; } public String getSex() { return sex; } public void setId(int id) { this.id = id; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public void setAddress(String address) { this.address = address; } public void setSex(String sex) { this.sex = sex; } @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", address='" + address + '\'' + ", sex='" + sex + '\'' + '}'; } } User實體類
(4)創建Mybatis核心配置文件(SqlMapConfig.xml)
在核心配置文件配置連接數據庫的相關信息,(如果是和Spring整合,則可以放在Spring配置文件中進行對數據庫的配置)
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!--加載資源文件--> <!-- <properties resource="jdbc.properties"></properties> <!–settings配置LOG4J輸出日志 –> <settings> <setting name="logImpl" value="LOG4J"/> </settings>--> <!--typeAliases配置包的別名--> <!--environments配置了數據庫連接,配置了driver、url、username、password屬性--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"> <!--<property name="" value="" />--> </transactionManager> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql:///mybatis01" /> <property name="username" value="root" /> <property name="password" value="123" /> </dataSource> </environment> </environments> <!--配置一個SQL語句和映射的配置文件--> <mappers> <mapper resource="UserMapper.xml" /> </mappers> </configuration> Mybatis核心配置文件
(5)創建一個Mapper.xml文件,對應編寫所需要的Sql查詢操作
<?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指定了命名空間--> <mapper namespace="test"> <!--定義一個SELECT查詢--> <!--parameterType:指定輸入參數的類型--> <!--#{}表示占位符--> <!--#{id}:其中的id表示的就是接受的輸入參數, 參數名稱就是id, 這里指出:如果輸入參數是簡單類型,#{}中的參數名可以任意設置(value或者其他名稱)--> <!--resultType:指定輸出類型(即指定輸出結果所映射的Java對象類型)--> <select id="findUserById" parameterType="int" resultType="cn.mybatis.po.User"> SELECT * FROM t_user WHERE id = #{id} </select> </mapper> UserMapper配置文件
(7)創建測試程序,對剛剛編寫的select查詢進行測試
package cn.mybatis.first; import cn.mybatis.po.User; 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 java.io.IOException; import java.io.InputStream; public class Test { public User findUserById() throws IOException { //得到mybatis配置文件 String resource = "SqlMapConfig.xml"; //得到配置文件的文件流信息 InputStream inputStream = Resources.getResourceAsStream(resource); //創建會話工廠 傳入mybatis的配置文件信息 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //通過會話工廠得到SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //通過sqlSession來操作數據庫 //第一個參數就是映射文件中statment的id:namespace +statment的id //第二個參數就是制定映射文件中的parameterType類型的參數 User user = sqlSession.selectOne("test.findUserById",1); //System.out.println(user); //釋放會話資源 try { sqlSession.close(); } catch (Exception e) { e.printStackTrace(); } return user; } public static void main(String[] args) { // TODO Auto-generated method stub Test test = new Test(); try { System.out.println(test.findUserById()); } catch (IOException e) { e.printStackTrace(); } } } Test測試程序
(8)加入Log4j日志文件
### direct log messages to stdout ### log4j.rootLogger=DEBUG, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n Log4j.properties
(9)測試結果
4.其他CRUD操作
(1)insert操作
在Mapper文件中添加響應的SQL配置,以及使用MySQL中的LAST_INSERT_ID()函數得到增加的數據的主鍵值
<insert id="addUser" parameterType="cn.mybatis.po.User"> <!-- 現在需要得到剛剛插入的記錄中的主鍵值,只適用于自增主鍵的情況 LAST_INSERT_ID() keyProperty:將查詢到的主鍵值設置到parameterType指定對象中的那個屬性 order:指定相對于insert的順序 resultType:指定映射結果的結果類型 --> <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> SELECT LAST_INSERT_ID() </selectKey> INSERT INTO t_user(id,username,password,address,sex) VALUES(#{id},#{username},#{password},#{address}, #{sex}); </insert>
插入數據的日志信息,沒有使用sqlSession.commit();之前的日志情況
從上面的圖中可以看出,沒有添加commit的時候,事務進行了回滾,所以要想添加數據,需要自己手動提交(在沒有整合Spring之前)
附上insertUser的函數
public void inserUser() throws IOException { //得到配置文件的文件流信息 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); User user = new User("World","1234","武漢市","男"); sqlSession.insert("test.addUser",user); System.out.println(user.getId()); sqlSession.commit(); //釋放會話資源 try { sqlSession.close(); } catch (Exception e) { e.printStackTrace(); } } inserUser函數
(2)模糊查詢
首先配置Mapper文件,${}和#{}的簡單區別如下:
<!-- 模糊查詢可能會查詢多條記錄 resultType:指定的就是查詢結果對應的單條記錄類型 ${}:表示將輸入的參數不加任何的修飾,直接作為字符串拼接在SQL中 但是這樣直接拼接,容易導致SQL注入的隱患 ${value}中的value表示接受的輸入參數,注意如果輸入參數是簡單類型,其中的形參只能用value --> <select id="findUserByUsername" parameterType="java.lang.String" resultType="cn.mybatis.po.User"> SELECT * FROM t_user WHERE username LIKE '%${value}%' </select>
使用查詢的時候碰到一個小錯誤,由于之前測試的insert方法,其中在User實體類中添加了有參構造函數,所以出現了下面的錯誤,分析原因就是:使用Mybatis查詢的時候需要在實體類中加入無參構造方法(當然如果實體類本身沒有構造函數,就會是默認的無參構造函數)
附上findByUsername的函數實現
public void findUserByUsername() throws IOException { //得到配置文件的文件流信息 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); List<User> userList = sqlSession.selectList("test.findUserByUsername","u"); System.out.println(userList); //釋放會話資源 try { sqlSession.close(); } catch (Exception e) { e.printStackTrace(); } } findByUsername函數實現
(3)刪除操作
首先在Mapper中配置刪除的操作
<delete id="deleteUser" parameterType="java.lang.Integer"> DELETE FROM t_user WHERE id = #{value} </delete>
運行測試程序,同insert中一樣,需要手動提交事務,如下面所示
最終結果:
數據表中刪除了編號為10的數據記錄
5.細節整理
(1)關于示例程序中一些相關類的理解
a)SqlSessionFactoryBuilder
用來創建SqlSessionFactory。因為SqlSessionFactory使用了單例模式,所以不需要使用單例模式來管理SqlSessionFactoryBuilder,只需要在創建SqlSessionFactory時 候使用一次就可以
b)SqlSessionFactory
會話工廠,用來創建SqlSession。可以使用單例模式來管理SqlSessionFactory這個會話工廠,工廠創建之后,就一直使用一個實例。
c)SqlSession
面向程序員的接口,提供了操作數據庫的方法。SqlSession是線程不安全的(原因:在SqlSession實現類中除了接口中的操作數據庫的方法之外,還有數據域的屬性,比如說一些提交的數據等等,所以在多線程并發請求的時候,會導致線程不安全),所以我們可以將SqlSession使用在方法體里面,這樣每個線程都有自己的方法,就不會沖突
(2)Mybatis中mapper映射文件
如同解釋Mybatis執行原理的時候一樣,Mapper映射文件中配置的Sql語句,實際上在執行的時候都被封裝稱為一個個MapperStatment對象,即Mapper映射文件是按照statment來管理不同的Sql。在編寫程序的時候,我們在使用SqlSession其中的操作數據庫的方法(selectOne,selectList等等)的時候,傳入的參數除了實參(id,模糊查詢的字符串等等)之外,還需要傳入的就是相應的Sql位置,而Sql是被Statment管理,所以就是傳入namespace+statmentId
(3)占位符
#{id}:其中的id表示的就是接受的輸入參數,參數名稱就是id,這里指出:如果輸入參數是簡單類型,#{}中的參數名可以任意設置(value或者其他名稱)
${value}:表示將輸入的參數不加任何的修飾,直接作為字符串拼接在SQL中但是這樣直接拼接,容易導致SQL注入的隱患${value}中的value表示接受的輸入參數,注意如果輸入參數是簡單類型,其中的形參只能用value
(4)別名定義
①單個別名的定義
<typeAliases> <!--針對單個別名的定義--> <typeAlias type="cn.mybatis.po.User" alias="user"></typeAlias> </typeAliases>
定義別名后的使用
<select id="findUserByIdTest" parameterType="int" resultType="user"> SELECT * FROM t_user WHERE id = #{id} </select>
②批量別名的定義
<typeAliases> <!--批量別名定義:Mybatis在定義別名的時候會自動掃描包中的po類,自動的將別名定義為類名(首字母大寫或者小寫都可以)--> <package name="cn.mybatis.po"></package> </typeAliases>
(5)在SqlMapConfig.xml中加載Mapper映射文件的時候,除了通過resource的方式,還可以使用mapper接口加載的方式來實現
①首先先注意一點:
在配置mybatis-config.xml時,其中的節點是有順序的,配置順序依次為:
properties/settings/typeAliases/typeHandlers/objectFactory/objectWrapperFactory/plugins/environments/databaseIdProvider/mappers
②使用mapper加載的方式,要將mapper接口和mapper配置文件放在同一目錄下面,并且文件名稱一致,而且要遵循mapper代理的方式進行開發
<mappers> <mapper class="cn.mybatis.mapper.UserMapper"></mapper> </mappers>
6.Mybatis開發dao方法簡介
(1)使用dao接口+實現類的方式
a)首先編寫接口,如同一般編寫模式方式進行編寫
package cn.mybatis.dao; import cn.mybatis.po.User; /** * 原始Dao方式開發:dao接口+dao實現類的方式 */ public interface UserDao { //根據id查詢信息 public User findUserById(int id) throws Exception; //添加信息 public void insertUser(User user) throws Exception; //刪除信息 public void deleteUser(int id) throws Exception; } dao接口
b)然后編寫接口實現
package cn.mybatis.dao.daoImpl; import cn.mybatis.dao.UserDao; import cn.mybatis.po.User; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.junit.Test; public class UserDaoImpl implements UserDao { //使用構造方法注入SqlSessionFactory private SqlSessionFactory sqlSessionFactory; public UserDaoImpl(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; } @Override @Test public User findUserById(int id) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); User user = sqlSession.selectOne("test.findUserById",id); sqlSession.close(); return user; } @Override public void insertUser(User user) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); // User user1 = new User("test1","123","洪山區","男"); sqlSession.insert("test.findUserById",user); sqlSession.commit(); sqlSession.close(); } @Override public void deleteUser(int id) throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); sqlSession.delete("test.findUserById",id); sqlSession.commit(); sqlSession.close(); } } dao接口實現類
c)Mapper配置文件和SqlConfig配置文件不變
d)使用Junit進行測試
package cn.mybatis.testdao; import cn.mybatis.dao.UserDao; import cn.mybatis.dao.daoImpl.UserDaoImpl; import cn.mybatis.po.User; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.InputStream; public class UserDaoImplTest { private SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception { InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserById() throws Exception{ //創建UserDao的對象 UserDao userDao = new UserDaoImpl(sqlSessionFactory); //調用UserDao的方法 User user = userDao.findUserById(1); System.out.println(user ); } } Junit測試
e)測試結果
f)原始dao方法的問題
①dao接口實現中存在大量的模板方法(即很多重復性的代碼 )
②調用SqlSession方法的時候將statmentid硬編碼了
③條用SqlSession方法的時候傳入的參數,由于使用泛型,所以在編譯階段不會報錯(即使傳入參數錯誤)
(2)使用Mapper代理的方法(即只需要Mapper接口)
(a)使用mapper方式的規范
①在使用mapper代理的方式中,namespace的值應該是mapper接口的路徑
②在mapper.java接口文件中的接口方法名稱和mapper.xml中的statment的id一致
③在mapper.java接口文件中的接口方法的輸入參數和mapper.xml中的statment的parameterType一致
④在mapper.java接口文件中的接口方法的返回值類型和mapper.xml中的statment的resultType一致
(b)查詢、刪除操作實例
①編寫mapper.xml配置文件,其中包含select和delete的sql配置
<?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指定了命名空間--> <!--在使用mapper代理的方式中,namespace的值應該是mapper接口的路徑--> <mapper namespace="cn.mybatis.mapper.UserMapper"> <select id="findUserById" parameterType="int" resultType="cn.mybatis.po.User"> SELECT * FROM t_user WHERE id = #{id} </select> <delete id="deleteUser" parameterType="java.lang.Integer"> DELETE FROM t_user WHERE id = #{value} </delete> </mapper> mapper.xml配置文件
②編寫mapper接口,按照mapper代理的方式開發規范來編寫mapper的接口
package cn.mybatis.testmapper; import cn.mybatis.mapper.UserMapper; import cn.mybatis.po.User; 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.After; import org.junit.Before; import org.junit.Test; import java.io.InputStream; public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception { InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserById() throws Exception{ SqlSession sqlSession = sqlSessionFactory.openSession(); //得到UserMapper的代理對象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.findUserById(9); System.out.println(user); } @Test public void testDeleteUser() throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.deleteUser(9); sqlSession.commit(); } @After public void tearDown() throws Exception { } } mapper接口
③Junit測試
package cn.mybatis.testmapper; import cn.mybatis.mapper.UserMapper; import cn.mybatis.po.User; 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.After; import org.junit.Before; import org.junit.Test; import java.io.InputStream; public class UserMapperTest { private SqlSessionFactory sqlSessionFactory; @Before public void setUp() throws Exception { InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } @Test public void testFindUserById() throws Exception{ SqlSession sqlSession = sqlSessionFactory.openSession(); //得到UserMapper的代理對象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = userMapper.findUserById(8); System.out.println(user); } @Test public void testDeleteUser() throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper userMapper = sqlSession.getMapper(UserMapper.class); userMapper.deleteUser(8); } @After public void tearDown() throws Exception { } } Junit測試
④查詢結果展示
⑤刪除結果展示
關于“Mybatis怎么用”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。