Mybatis 入門案例分享
本文分享一下,Mybatis的一些入門案例;
為什麽不用JDBC方式來操作數據庫,而使用類似於Mybatis的框架呢?
1、 數據庫鏈接創建、釋放頻繁造成系統資源浪費從而影響系統性能,如果使用數據庫鏈接池可解決此問題。
解決:在SqlMapConfig.xml中配置數據鏈接池,使用連接池管理數據庫鏈接。
2、 Sql語句寫在代碼中造成代碼不易維護,實際應用sql變化的可能較大,sql變動需要改變java代碼。
解決:將Sql語句配置在XXXXmapper.xml文件中與java代碼分離。
3、 向sql語句傳參數麻煩,因為sql語句的where條件不一定,可能多也可能少,占位符需要和參數一一對應。
解決:
4、 對結果集解析麻煩,sql變化導致解析代碼變化,且解析前需要遍歷,如果能將數據庫記錄封裝成pojo對象解析比較方便。
解決:Mybatis自動將sql執行結果映射至java對象,通過statement中的resultType定義輸出結果的類型。
一、需求:
根據用戶id查詢一個用戶信息
根據用戶名稱模糊查詢用戶信息列表
添加用戶
更新用戶
刪除用戶
二、環境搭建
第一、創建maven工程,添加mybatis依賴、mysql驅動等依賴,pom文件如下;
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.xingej.mybatis</groupId> <artifactId>itcast-mybatis</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>itcast-mybatis</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- 數據庫驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.39</version> </dependency> <!-- mybatis依賴 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.5</version> </dependency> <!-- log4j 日誌依賴 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </project>
第二、添加SqlMapConfig.xml配置文件
<?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> <!-- 和spring整合後 environments配置將廢除--> <environments default="development"> <environment id="development"> <!-- 使用jdbc事務管理--> <transactionManager type="JDBC" /> <!-- 數據庫連接池--> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <mappers> <mapper resource="sqlMap/User.xml"/> </mappers> </configuration>
第三、創建po類
package com.xingej.mybatis.po; import java.util.Date; /** * po類,就是屬性+get/set方法 * * @author erjun * */ public class User { private int id; private String username;// 用戶姓名 private String sex;// 性別 private Date birthday;// 生日 private String address;// 地址 public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User [id=" + id + ", username=" + username + ", sex=" + sex + ", birthday=" + birthday + ", address=" + address + "]"; } }
第四、編寫po類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命名空間,為了對sql語句進行隔離,方便管理 ,mapper開發dao方式,使用namespace有特殊作用 --> <mapper namespace="test"> <!-- 在mapper.xml文件中配置很多的sql語句,執行每個sql語句時,封裝為MappedStatement對象 mapper.xml以statement為單位管理sql語句 --> <!-- 根據id查詢用戶信息 --> <!-- id:唯一標識 一個statement #{}:表示 一個占位符,如果#{}中傳入簡單類型的參數,#{}中的名稱隨意 parameterType:輸入 參數的類型,通過#{}接收parameterType輸入 的參數 resultType:輸出結果 類型,不管返回是多條還是單條,指定單條記錄映射的pojo類型 --> <select id="findUserById" parameterType="int" resultType="com.xingej.mybatis.po.User"> SELECT * FROM USER WHERE id= #{id} </select> <!-- 根據用戶名稱查詢用戶信息,可能返回多條 ${}:表示sql的拼接,通過${}接收參數,將參數的內容不加任何修飾拼接在sql中。 ${}方式的缺點:不能防止sql的註入;select * from user where name like ‘xiaoming‘ or ‘1=1‘ 這條語句,始終成立,後面的‘ or ‘1= 就是sql註入; 有的時候,軟件在交付的時候,會進行sql註入的校驗。 --> <select id="findUserByName" parameterType="java.lang.String" resultType="com.xingej.mybatis.po.User"> select * from user where username like ‘%${value}%‘ </select> <!-- 添加用戶 parameterType:輸入 參數的類型,User對象 包括 username,birthday,sex,address #{}接收pojo數據,可以使用OGNL解析出pojo的屬性值 #{username}表示從parameterType中獲取pojo的屬性值 selectKey:用於進行主鍵返回,定義了獲取主鍵值的sql order:設置selectKey中sql執行的順序,相對於insert語句來說 keyProperty:將主鍵值設置到哪個屬性 resultType:select LAST_INSERT_ID()的結果 類型 --> <insert id="insertUser" parameterType="com.xingej.mybatis.po.User"> <selectKey keyProperty="id" order="AFTER" resultType="int"> select LAST_INSERT_ID() </selectKey> INSERT INTO USER(username,birthday,sex,address) VALUES(#{username},#{birthday},#{sex},#{address}) </insert> <!-- mysql的uuid生成主鍵 --> <!-- <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User"> <selectKey keyProperty="id" order="BEFORE" resultType="string"> select uuid() </selectKey> INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address}) </insert> --> <!-- oracle 在執行insert之前執行select 序列.nextval() from dual取出序列最大值,將值設置到user對象 的id屬性 --> <!-- <insert id="insertUser" parameterType="cn.itcast.mybatis.po.User"> <selectKey keyProperty="id" order="BEFORE" resultType="int"> select 序列.nextval() from dual </selectKey> INSERT INTO USER(id,username,birthday,sex,address) VALUES(#{id},#{username},#{birthday},#{sex},#{address}) </insert> --> <!-- 用戶刪除 --> <delete id="deleteUser" parameterType="int"> delete from user where id=#{id} </delete> <!-- 用戶更新 要求:傳入的user對象中包括 id屬性值 --> <update id="updateUser" parameterType="com.xingej.mybatis.po.User"> update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id} </update> </mapper>
補充說明:
三、編寫測試用例
package com.xingej.mybatis.first; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.List; 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.Before; import org.junit.Test; import com.xingej.mybatis.po.User; public class MybatisFirst { // 聲明一個全局的會話工廠 SqlSessionFactory sqlSessionFactory = null; // 創建session工廠 @Before public void init() throws IOException { // 1、配置文件(SqlMapConfig.xml) String resource = "SqlMapConfig.xml"; // 2、加載配置文件,轉換成流 InputStream inputStream = Resources.getResourceAsStream(resource); // 3、創建會話工廠SessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } // 根據用戶ID查詢用戶(得到單條記錄) @Test public void testFindUserById() { // 1、通過session工廠來創建一個session SqlSession sqlSession = sqlSessionFactory.openSession(); // 2、通過session會話來操作數據庫 // 第一個參數:statement位置:就是namespace + statement的id // 第2個參數:就是你傳入的參數 User user = null; try { user = sqlSession.selectOne("test.findUserById", 1); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } System.out.println("----user-----:\t" + user); } // 根據用戶名稱來查詢, // 返回結果是List類型 // 支持模糊查詢 @Test public void testFindUserByName() { // 1、獲取session會話 SqlSession sqlSession = sqlSessionFactory.openSession(); // 2、操作數據庫 List<User> users = null; try { users = sqlSession.selectList("test.findUserByName", "小明"); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } System.out.println("----->:\t" + users.get(2).getUsername()); } // 插入一條記錄 @Test public void testInsertUser() { // 1、通過session工廠來創建一個session SqlSession sqlSession = sqlSessionFactory.openSession(); // 2、通過session會話來操作數據庫 User user = new User(); user.setAddress("北京"); user.setBirthday(new Date()); user.setSex("1"); user.setUsername("浪子燕青"); try { sqlSession.insert("test.insertUser", user); // 提交事務,千萬別忘記 sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } System.out.println("----user-----:\t" + user); } // 更新一條記錄 @Test public void testUpdateUser() { // 1、通過session工廠來創建一個session SqlSession sqlSession = sqlSessionFactory.openSession(); // 2、通過session會話來操作數據庫 User user = new User(); user.setId(16); user.setAddress("北京"); user.setBirthday(new Date()); user.setSex("1"); user.setUsername("故、新"); try { sqlSession.update("test.updateUser", user); // 提交事務,千萬別忘記 sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } System.out.println("----user-----:\t" + user); } // 刪除一條記錄 @Test public void testDeleteUser() { // 1、通過session工廠來創建一個session SqlSession sqlSession = sqlSessionFactory.openSession(); // 2、通過session會話來操作數據庫 try { sqlSession.update("test.deleteUser", 26); // 提交事務,千萬別忘記 sqlSession.commit(); } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } } }
總結:
1、SqlMapConfig.xml 文件
是mybatis全局配置文件,只有一個,名稱不固定的,主要mapper.xml,mapper.xml中配置 sql語句
2、mapper.xml文件
mapper.xml是以statement為單位進行配置。(把一個sql稱為一個statement),satatement中配置 sql語句、parameterType輸入參數類型(完成輸入映射)、resultType輸出結果類型(完成輸出映射)。
還提供了parameterMap配置輸入參數類型(過期了,不推薦使用了)
還提供resultMap配置輸出結果類型(完成輸出映射),通過resultMap完成復雜數據類型的映射(一對多,多對多映射)
3、#{} 符號說明:
表示一個占位符,向占位符輸入參數,mybatis自動進行java類型和jdbc類型的轉換。
程序員不需要考慮參數的類型,比如:傳入字符串,mybatis最終拼接好的sql就是參數兩邊加單引號。
#{}接收pojo數據,可以使用OGNL解析出pojo的屬性值
4、${} 符號說明:
表示sql的拼接,通過${}接收參數,將參數的內容不加任何修飾拼接在sql中。
${}也可以接收pojo數據,可以使用OGNL解析出pojo的屬性值
缺點:不能防止sql註入。
例如:select * from user where name like ‘xiaoming‘ or ‘1=1‘
這條語句,始終成立,後面的 ‘ or ‘1= 就是sql註入
代碼已經上傳到git上:
https://github.com/xej520/xingej-mybatis
本文出自 “XEJ分布式工作室” 博客,請務必保留此出處http://xingej.blog.51cto.com/7912529/1979119
Mybatis 入門案例分享