11:30:27
Mybatis+mysql 入門使用
Mybatis+mysql 配置文件版本入門使用
Mybatis+mysql 注解版本入門使用
一、新建一個java maven項目-Mybatis+mysql 配置文件版本入門使用
groupId:cn.zc.javapro.database
artifactId:SimpleMybatisMysql
version:1.0-SNAPSHOT
,目錄結構如下所示:

1、添加依賴
a)使用maven管理依賴,以我本次使用的版本為例
<?xml version="1.0" encoding="UTF-8"?> <!--MyBatis 是一款優秀的持久層框架,它支持定制化 SQL、存儲過程以及高級映射。 框架:Mybatis+mysql入門使用 入門使用 1、添加依賴 a、使用maven管理依賴,以我本次使用的版本為例--> <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>cn.zc.javapro.database</groupId> <artifactId>SimpleMybatisMysql</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.13</version> <scope>runtime</scope> </dependency> <!--druid連接池--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <!--lombok 注解--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> </configuration> </plugin> </plugins> </build> </project>
b) 也可以使用gradle管理依賴
c) 也可以去官網下載,mybatis-3官網地址:http://www.mybatis.org/mybatis-3/
2、初始化數據庫和初始數據
以數據庫db2021和表t_test為例,以下是sql。然后執行sql,經此步驟,數據庫中存在數據庫db2021和表t_test
-- 2、初始化數據庫和初始數據,以數據庫moy_mybatis和表t_test為例
-- 創建數據庫
CREATE SCHEMA IF NOT EXISTS `db2021` Character Set utf8mb4 COLLATE utf8mb4_unicode_ci;
USE `db2021`; -- 創建一個測試表 CREATE TABLE IF NOT EXISTS `db2021`.`t_test`( id INT(11) AUTO_INCREMENT, create_time DATE COMMENT '創建時間', modify_time DATE COMMENT '修改時間', content VARCHAR (50) COMMENT '內容', PRIMARY KEY (id) );
3、新建實體類TestEntity.java
為了接收從表中取出來的值,比如數據庫的select語句返回來的值,我們通過實體類對象進行接收。所以需要定義表的實體類。
關鍵技術點是Mybatis如何實現封裝,如何實現表列和實體類對象成員之間的一一映射。
package cn.zc.javapro.database.mybatis.entity; import lombok.Getter; import lombok.Setter; import lombok.ToString; import java.io.Serializable; import java.util.Date; /** * [Project]: * [Date]:2021/1/22 * [Description]: java mybatis mysql maven * @author zc */ //讓它實現序列化接口 @Getter @Setter @ToString public class TestEntity implements Serializable { private Integer id; private Date createTime; private Date modifyTime; private String content; }
這里我們可以玩個小花樣,再用個實體類QueryVo封裝一下TestEntity實體類。
package cn.zc.javapro.database.mybatis.domain; import cn.zc.javapro.database.mybatis.entity.TestEntity; public class QueryVo { private TestEntity testEntity; public TestEntity getTestEntity() { return testEntity; } public void setTestEntity(TestEntity testEntity) { this.testEntity = testEntity; } }
4、新建接口TestMapper.java
Mybatis通過定義接口,並通過配置文件或者注解,自動實現將該接口中的方法與sql語句一一對應。
當調用該接口的方法,相當於調用了對應的sql語句。
package cn.zc.javapro.database.mybatis.mapper; import cn.zc.javapro.database.mybatis.domain.QueryVo; import cn.zc.javapro.database.mybatis.entity.TestEntity; import org.apache.ibatis.annotations.Param; import java.io.Serializable; import java.util.List; /** * [Project]: * [Email]: * [Date]:2021/1/22 * [Description]: * * @author zc */ public interface TestMapper { List<TestEntity> list(); TestEntity get(Serializable id); //TestEntity get(Integer id); //TestEntity get(@Param("id") Integer id); int insert(TestEntity TestEntity); int update(TestEntity TestEntity); int delete(Serializable id); int count(); /** * 根據名稱模糊查詢信息 */ List<TestEntity> findByContent(String content); /** * 根據queryVo中的條件查詢用戶 */ List<TestEntity> findTestByVo(QueryVo vo); }
5、 新建實體映射文件Test.xml
這里主要配置 接口類的方法 與 sql語句一一對應關系。比如, TestMapper 與 TestEntity、QueryVo等。
這里的namespace就是寫TestMapper全類名,否則不能使用動態代理的方式調用接口TestMapper。后面會講一下parameterType如何配置多個參數。
<?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">
<!--新建實體映射文件Test.xml,這里的namespace就是寫TestMapper全類名,否則不能使用動態代理的方式調用接口TestMapper-->
<mapper namespace="cn.zc.javapro.database.mybatis.mapper.TestMapper">
<!--配置 查詢結果的列明和實體類的屬性名的對應關系-->
<resultMap id="testMap" type="TestEntity">
<!--主鍵字段的對應 -->
<id property="id" javaType="Integer" column="id"></id>
<!--非主鍵字段的對應-->
<result property="createTime" javaType="Date" column="create_time"></result>
<result property="modifyTime" javaType="Date" column="modify_time"></result>
<result property="content" javaType="String" column="content"></result>
</resultMap>
<!--<select id="list" resultType="TestEntity">
SELECT * FROM t_test
</select>-->
<select id="list" resultMap="testMap">
SELECT * FROM t_test
</select>
<!--<select id="list" resultType="TestEntity">
SELECT id,create_time as createTime,modify_time as modifyTime ,content
FROM t_test
</select>-->
<select id="count" resultType="int">
SELECT count(*) FROM t_test
</select>
<!-- 如果 mybatis-config.xml 中沒有配置實體類對應的包名,則 resultType="cn.zc.javapro.database.mybatis.entity.TestEntity" -->
<!-- 這里數據庫返回值TestEntity的成員變量,肯定需要用到成員變量的set方法,
要想賦值給對的對象,必須將表的列名和對象的成員變量一一對應起來。
select可以通過給列名起別名為對象的成員變量名,建立一一對應關系,如下 create_time as createTime,create_time是表的列名,createTime是TestEntity的成員變量
insert如下所示
update如下所示
-->
<select id="get" parameterType="int" resultType="TestEntity">
SELECT id,create_time as createTime,modify_time as modifyTime, content
FROM t_test WHERE id=#{id}
</select>
<insert id="insert" parameterType="TestEntity">
<!--配置插入操作后,獲取插入數據的id-->
<!--<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>-->
INSERT INTO t_test (create_time,modify_time,content)
VALUES (#{createTime},#{modifyTime},#{content})
</insert>
<update id="update" parameterType="TestEntity">
UPDATE t_test SET modify_time=#{modifyTime},content=#{content}
WHERE id = #{id}
</update>
<delete id="delete" parameterType="int">
DELETE FROM t_test WHERE id = #{id}
</delete>
<select id="findByContent" parameterType="string" resultType="TestEntity">
<!-- 有問題: select * from t_test where content like #{content}; -->
select id, create_time as createTime, modify_time as modifyTime, content
from t_test where content like '%${content}%'
</select>
<!--根據queryVo的條件查詢用戶-->
<select id="findTestByVo" parameterType="cn.zc.javapro.database.mybatis.domain.QueryVo" resultType="TestEntity">
<!--select * from t_test where id like #{testEntity.id};-->
select id, create_time as createTime, modify_time as modifyTime, content
from t_test where id like #{testEntity.id};
</select>
</mapper>
6、新建mybatis配置信息文件mybatis-config.xml
這里主要配置項目實體類對應的包名,可以掃描實體類。並配置了mysql數據庫的連接信息。以及配置了 接口類與實體類映射的配置文件(這里例如Test.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"> <!--新建mybatis配置信息文件mybatis-config.xml--> <!--首先是跟元素--> <configuration> <typeAliases> <!--項目實體類對應的包名--> <package name="cn.zc.javapro.database.mybatis.entity"/> </typeAliases> <!--myql數據庫連接信息--> <!--配置環境 , 選擇一個默認的環境mysql--> <environments default="development"> <!--配置mysql的環境--> <environment id="development"> <!--配置事務--> <transactionManager type="JDBC"/> <!--配置連接池--> <!--<dataSource type="cn.zc.javapro.database.mybatis.datasource.MyDataSource">--> <dataSource type="POOLED"> <!--<property name="driver" value="com.mysql.jdbc.Driver"/>--> <!--<property name="url" value="jdbc:mysql://127.0.0.1:3306/db2021?useSSL=false"/>--> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!--配置實體映射xml路徑--> <mappers> <mapper resource="mapper/Test.xml"></mapper> </mappers> </configuration>
這里重點說一下,我們可以單獨通過XML來配置環境變量。
也可以通過 xml + properties 文件進行配置,
也可以通過 properties + xml文件進行配置,
還可以通過 yml + xml 文件進行配置。
參考: SpringBoot配置Mybatis的兩種方式(通過XML配置和通過YML配置文件配置): https://blog.csdn.net/weixin_43966635/article/details/112342116
比如,xml的配置還有另一種寫法,即 xml + properties,下面的只寫主要部分:
1.內置連接池 <configuration> <environments default="development"> <environment id="development"> <!-- 配置事務管理器 --> <transactionManager type="JDBC"/> <!-- 配置數據源:這里使用 MyBatis 內置連接池 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql:///mybatisstu"/> <property name="username" value="root"/> <property name="password" value="123"/> </dataSource> </environment> </environments> </configuration> 2.引入數據源 <configuration> <!--引入數據源--> <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="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>
7、為了方便測試,編寫一個獲取SqlSession的工具類MybatisTools.java
該類主要通過配置文件(如,mybatis-config.xml)初始化 SqlSession,通過SqlSession 配置注冊初始化 接口類(如 TestMapper)
package cn.zc.javapro.database.mybatis.tools; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.ExecutorType; 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.Reader; import java.util.Objects; /** * [Project]: * [Email]: * [Date]:2021/1/22 * [Description]: * 7、為了方便測試,編寫一個獲取SqlSession的工具類MybatisTools * 該類主要是加載mybatis的配置文件(如:mybatis-config.xml等),然后 * * 使用的時候: * 1)先 MybatisTools mt = new MybatisTools(resourceXMLFile) // 這里的resourceXMLFile是mybatis的配置文件,如"mybatis-config.xml" * 2) SqlSession sqlSession = mt.openCurrentSqlSession() // 按照配置文件打開獲取 SqlSession * 3) TestMapper testMapper = sqlSession.getMapper(TestMapper.class); // 這里的 TestMapper.class 是實體和數據庫的交互接口。 * 4) testMapper.getAll() // 調用方法 * 5) mt.closeCurrentSqlSession() // 關閉 SqlSession * @author zc */
public class MybatisTools { //private String resourceFile;
private ExecutorType executorType; private SqlSessionFactory sqlSessionFactory; private ThreadLocal<SqlSession> sessionThread = new ThreadLocal<>(); /** * * @param resourceFile 資源文件 */
public MybatisTools(String resourceFile) { //this.resourceFile = resourceFile;
this.initSqlSessionFactory(resourceFile); } /** * * @param resourceFile * @param executorType */
public MybatisTools(String resourceFile, ExecutorType executorType) { //this.resourceFile = resourceFile;
this.initSqlSessionFactory(resourceFile); this.executorType = executorType; } private void initSqlSessionFactory(String resourceFile) { try { Reader reader = Resources.getResourceAsReader(resourceFile); // 構建sqlSession的工廠
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (IOException e) { throw new RuntimeException(e); } } public SqlSession openCurrentSqlSession() { SqlSession sqlSession = sessionThread.get(); if (Objects.isNull(sqlSession)) { if(this.executorType == null) { sqlSession = sqlSessionFactory.openSession(); } else { // 通過session設置ExecutorType開啟批量添加,類似jdbc的addBatch操作 //sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
sqlSession = sqlSessionFactory.openSession(this.executorType); } sessionThread.set(sqlSession); } return sqlSession; } public void commitCurrentSqlSession() { SqlSession sqlSession = sessionThread.get(); if (Objects.nonNull(sqlSession)) { sqlSession.commit(); } } public void closeCurrentSqlSession() { SqlSession sqlSession = sessionThread.get(); if (Objects.nonNull(sqlSession)) { /*if (this.executorType != null) { sqlSession.commit(); }*/ sqlSession.close(); } sessionThread.set(null); } }
執行查詢語句的時候不需要commit,但是執行 insert、update等操作時,需要commit。並且如果是大批量的更新插入操作,則每次都打開關閉,會浪費。所以我們直接一次插入。具體看第八節。
8、 新建測試類TestMapperTest測試
包括3步:開啟SqlSession;執行接口類的方法(如TestMapper的get()方法 );關閉SqlSession。
package cn.zc.javapro.database.mybatis.mapper; import cn.zc.javapro.database.mybatis.domain.QueryVo; import cn.zc.javapro.database.mybatis.entity.TestEntity; import cn.zc.javapro.database.mybatis.tools.MybatisTools; import cn.zc.javapro.database.mybatis.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.util.Arrays; import java.util.Date; import java.util.List; public class TestMapperTest { MybatisTools mybatisTools; SqlSession sqlSession; TestMapper testMapper; @Before public void before() { /*sqlSession = MybatisUtils.getCurrentSqlSession(); testMapper = sqlSession.getMapper(TestMapper.class);*/ mybatisTools = new MybatisTools("mybatis-config.xml"); sqlSession = mybatisTools.openCurrentSqlSession(); testMapper = sqlSession.getMapper(TestMapper.class); } @After public void after() { // MybatisUtils.closeCurrentSession(); mybatisTools.closeCurrentSqlSession(); } @Test public void insert() { TestEntity entity = new TestEntity(); entity.setCreateTime(new Date()); entity.setModifyTime(new Date()); entity.setContent("我是內容"); //entity.setaontent("我是內容"); System.out.println(testMapper.insert(entity)); sqlSession.commit(); } @Test public void count() { System.out.println(testMapper.count()); } @Test public void list() { List<TestEntity> list = testMapper.list(); //System.out.println(Arrays.toString(list.toArray())); for (TestEntity testEntity : list) { System.out.println(testEntity); } } @Test public void get() { System.out.println(testMapper.get(1)); } @Test public void update() { TestEntity entity = new TestEntity(); entity.setId(1); entity.setModifyTime(new Date()); entity.setContent("我是修改后內容"); //entity.setaontent("我是修改后內容"); testMapper.update(entity); sqlSession.commit(); } @Test public void delete() { testMapper.delete(1); sqlSession.commit(); } /** * 測試模糊查詢操作 */ @Test public void findByContent(){ List<TestEntity> testEntityList = testMapper.findByContent("內容"); for(TestEntity testEntity: testEntityList){ System.out.println(testEntity); } } /** * 測試使用QueryVo作為查詢對象 */ @Test public void testFindByVo(){ QueryVo vo = new QueryVo(); TestEntity testEntity = new TestEntity(); //testEntity.setContent("%內容%"); testEntity.setId(1); vo.setTestEntity(testEntity); List<TestEntity> testEntityList = testMapper.findTestByVo(vo); for(TestEntity testEntity1 : testEntityList){ System.out.println(testEntity1); } } }
我們可以看到,已經可以操作了。下面我們試一下主方法中調用:
9、主方法中調用
包括3步:開啟SqlSession;執行接口類的方法(如TestMapper的get()方法 );關閉SqlSession。
package cn.zc.javapro.database.mybatis; import cn.zc.javapro.database.mybatis.mapper.TestMapper; import cn.zc.javapro.database.mybatis.tools.MybatisTools; import cn.zc.javapro.database.mybatis.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; public class SimpleMybatisMysqlApp { public static void main(String[] args) { test2(); } public static void test2() { SqlSession sqlSession; TestMapper testMapper; // MybatisTools mybatisTools = new MybatisTools("mybatis-config.xml"); sqlSession = mybatisTools.openCurrentSqlSession(); //得到 TestMapper 接口的實現類對象,TestMapper 接口的實現類對象由 sqlSession.getMapper(TestMapper.class)動態構建出來 testMapper = sqlSession.getMapper(TestMapper.class); //執行查詢操作,將查詢結果自動封裝成 TestEntity 返回 System.out.println(testMapper.get(1)); mybatisTools.closeCurrentSqlSession(); } public static void test() { SqlSession sqlSession; TestMapper testMapper; sqlSession = MybatisUtils.getCurrentSqlSession(); testMapper = sqlSession.getMapper(TestMapper.class); // System.out.println(testMapper.get(1)); MybatisUtils.closeCurrentSession(); } }
可以看出來,依然可以得出結果。到這一步,我們已經可以使用mybatis對數據庫進行操作了。
二、Mybatis (ParameterType) 如何傳遞多個不同類型的參數
偶然碰到一個需要給xml傳一個String類型和一個Integer類型的需求,當時心想用map感覺有點太浪費,所以專門研究了下各種方式。
1、 方法一:不需要寫parameterType參數
public List<XXXBean> getXXXBeanList(String xxId, String xxCode);
<select id="getXXXBeanList" resultType="XXBean">
select t.* from tableName where id = #{0} and name = #{1}
</select>
由於是多參數那么就不能使用parameterType, 改用#{index}是第幾個就用第幾個的索引,索引從0開始
2、方法二:基於注解(最簡單)
public List<XXXBean> getXXXBeanList(@Param("id")String id, @Param("code")String code);
<select id="getXXXBeanList" resultType="XXBean">
select t.* from tableName where id = #{id} and name = #{code}
</select>
由於是多參數那么就不能使用parameterType, 這里用@Param來指定哪一個
3、方法三:Map封裝
public List<XXXBean> getXXXBeanList(HashMap map);
<select id="getXXXBeanList" parameterType="hashmap" resultType="XXBean">
select 字段... from XXX where id=#{xxId} code = #{xxCode}
</select>
其中hashmap是mybatis自己配置好的直接使用就行。map中key的名字是那個就在#{}使用那個,map如何封裝就不用了我說了吧。
4、方法四:List封裝
public List<XXXBean> getXXXBeanList(List<String> list);
<select id="getXXXBeanList" resultType="XXBean">
select 字段... from XXX where id in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")"> #{item} </foreach> </select>
5、總結
傳遞list和map在資源消耗上肯定遠大於方法一和方法二,但是有一些特殊的情形需要傳遞list,比如你需要傳遞一個id集合並批量對id進行sql操作然后再返回等等。所以都需要了解。
四、Mybatis (resultType) 返回結果
如何對應實體類的成員變量,之前說過我們實體類的屬性名和數據庫列名是一致的,那如果是不一致的呢。
因為MySQL數據庫不區分大小寫,userName和username等同所以能封裝進去,而其他的完全不一樣,就封裝不進去。
這里注意如果是linux系統是嚴格區分大小寫的。
現在我們來解決封裝不進去的問題,之所以封裝不進去就是名字對不上,我們可以通過起別名的方式解決。
有2種解決辦法:都是通過配置 Tese.xml .
1、通過起別名的方式
現在我們來解決封裝不進去的問題,之所以封裝不進去就是名字對不上,我們可以通過起別名的方式解決。
也就是說mysql執行這條sql語句出來的列名跟實體類是需要匹配的。如下所示:我們只是截取Test.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">
<!--新建實體映射文件Test.xml,這里的namespace就是寫TestMapper全類名,否則不能使用動態代理的方式調用接口TestMapper-->
<mapper namespace="cn.zc.javapro.database.mybatis.mapper.TestMapper">
<!--<select id="list" resultType="TestEntity">
SELECT * FROM t_test
</select>-->
<select id="list" resultType="TestEntity">
SELECT id,create_time as createTime,modify_time as modifyTime ,content
FROM t_test
</select>
<!-- 如果 mybatis-config.xml 中沒有配置實體類對應的包名,則 resultType="cn.zc.javapro.database.mybatis.entity.TestEntity" -->
<!-- 這里數據庫返回值TestEntity的成員變量,肯定需要用到成員變量的set方法,
要想賦值給對的對象,必須將表的列名和對象的成員變量一一對應起來。
select可以通過給列名起別名為對象的成員變量名,建立一一對應關系,如下 create_time as createTime,create_time是表的列名,createTime是TestEntity的成員變量
insert如下所示
update如下所示
-->
<select id="get" parameterType="int" resultType="TestEntity">
SELECT id,create_time as createTime,modify_time as modifyTime ,content
FROM t_test WHERE id=#{id}
</select>
<insert id="insert" parameterType="TestEntity">
<!--配置插入操作后,獲取插入數據的id-->
<!--<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>-->
INSERT INTO t_test (create_time,modify_time,content)
VALUES (#{createTime},#{modifyTime},#{content})
</insert>
<update id="update" parameterType="TestEntity">
UPDATE t_test SET modify_time=#{modifyTime},content=#{content}
WHERE id = #{id}
</update>
<delete id="delete" parameterType="int">
DELETE FROM t_test WHERE id = #{id}
</delete>
</mapper>
我們可以看到select 、insert、update、delete 都是將表列名和實體成員變量名對應起來。
如果我們用了
<select id="list" resultType="TestEntity"> SELECT * FROM t_test </select>
就會出現id和content有內容,而 createTime 和 modifyTime為 null。這是因為id和content表列名和對象成員變量一致,而表中create_time ,成員變量createTime ;表中modify_time,成員變量modifyTime名字不一致,Mybatis無法將之對應起來,無法賦值。
同理 insert、update、delete。
2、文檔進行一個配置,創建了一個結果集的關系表
創建了一個結果集的關系表,使得java實體類的屬性名和數據庫的列名一一對應,property是java屬性名,column是表的列名。
我們截取了Test.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"> <!--新建實體映射文件Test.xml,這里的namespace就是寫TestMapper全類名,否則不能使用動態代理的方式調用接口TestMapper--> <mapper namespace="cn.zc.javapro.database.mybatis.mapper.TestMapper"> <!--配置 查詢結果的列明和實體類的屬性名的對應關系--> <resultMap id="testMap" type="TestEntity"> <!--主鍵字段的對應 --> <id property="id" javaType="Integer" column="id"></id> <!--非主鍵字段的對應--> <result property="createTime" javaType="Date" column="create_time"></result> <result property="modifyTime" javaType="Date" column="modify_time"></result> <result property="content" javaType="String" column="content"></result> </resultMap> <select id="list" resultMap="testMap"> SELECT * FROM t_test </select> <!-- 如果 mybatis-config.xml 中沒有配置實體類對應的包名,則 resultType="cn.zc.javapro.database.mybatis.entity.TestEntity" --> <!-- 這里數據庫返回值TestEntity的成員變量,肯定需要用到成員變量的set方法, 要想賦值給對的對象,必須將表的列名和對象的成員變量一一對應起來。 --> <select id="get" parameterType="int" resultMap="testMap"> SELECT * FROM t_test WHERE id=#{id} </select> </mapper>
這樣就可以將表列名和對象成員變量一一對應起來。
總結
第一種方式是直接在數據庫層實現,第二種方式還要多解析個xml,所以第一種的執行效率比第二種的要高,但第二種的開發效率高,因為我們既然定義了這個map,之后有關查詢的都可以配置這個map,不用動里面的sql語句,兩種方法各有利弊。
五、Mybatis+mysql 注解版本入門使用
只需要簡單的修改就可以了,首先注解版本的實現就是用注解代替了Test.xml,所以注解版本不需要Test.xml。
1、修改 mybatis-config.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"> <!--新建mybatis配置信息文件mybatis-config.xml--> <!--首先是跟元素--> <configuration> <!--<settings> <!– #開啟mybatis駝峰式命名規則自動轉換 –> <setting name="mapUnderscoreToCamelCase" value="true" /> </settings>--> <typeAliases> <!-- <typeAlias alias="Integer" type="java.lang.Integer" /> <typeAlias alias="Long" type="java.lang.Long" /> <typeAlias alias="HashMap" type="java.util.HashMap" /> <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" /> <typeAlias alias="ArrayList" type="java.util.ArrayList" /> <typeAlias alias="LinkedList" type="java.util.LinkedList" />--> <!--項目實體類對應的包名--> <package name="cn.zc.javapro.database.mybatis.entity"/> </typeAliases> <!--myql數據庫連接信息--> <!--配置環境 , 選擇一個默認的環境mysql--> <environments default="development"> <!--配置mysql的環境--> <environment id="development"> <!--配置事務--> <transactionManager type="JDBC"/> <!--配置連接池--> <dataSource type="cn.zc.javapro.database.mybatis.datasource.MyDataSource"> <!--<dataSource type="POOLED">--> <!--<property name="driver" value="com.mysql.jdbc.Driver"/>--> <!--<property name="url" value="jdbc:mysql://127.0.0.1:3306/db2021?useSSL=false"/>--> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!-- 映射文件定位 --> <!--這個就是說一下,要執行的sql語句的xml文件在哪,這里可以寫相對路徑也可以寫絕對路徑,絕對路徑就是url,相對路徑使用resource--> <mappers> <!-- <mapper url = "file:Users/zc/MybatisMysqlAnnotation/src/main/resources/mapper/Test.xml" /> --> <!--配置實體映射xml路徑, 配置文件就用這個--> <!--<mapper resource="mapper/Test.xml"></mapper>--> <!-- 注冊Mapper映射接口,注解就用這個--> <mapper class = "cn.zc.javapro.database.mybatis.mapper.TestMapper2" /> </mappers> </configuration>
主要是修改了:
<!-- 映射文件定位 --> <!--這個就是說一下,要執行的sql語句的xml文件在哪,這里可以寫相對路徑也可以寫絕對路徑,絕對路徑就是url,相對路徑使用resource--> <mappers> <!-- <mapper url = "file:Users/zc/MybatisMysqlAnnotation/src/main/resources/mapper/Test.xml" /> --> <!--配置實體映射xml路徑, 配置文件就用這個--> <!--<mapper resource="mapper/Test.xml"></mapper>--> <!-- 注冊Mapper映射接口,注解就用這個--> <mapper class = "cn.zc.javapro.database.mybatis.mapper.TestMapper2" /> </mappers>
2、添加接口 TestMapper2.java
這里面就是注解的實現。
package cn.zc.javapro.database.mybatis.mapper; import cn.zc.javapro.database.mybatis.domain.QueryVo; import cn.zc.javapro.database.mybatis.entity.TestEntity; import org.apache.ibatis.annotations.Delete; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import java.io.Serializable; import java.util.List; /** * [Project]: * [Email]: * [Date]:2021/1/22 * [Description]: * * @author zc */ public interface TestMapper2 { @Select("select id, create_time as createTime, modify_time as modifyTime, content from t_test;") List<TestEntity> list(); @Select("select id, create_time as createTime, modify_time as modifyTime, content from t_test where id = #{id};") TestEntity get(Serializable id); //TestEntity get(Integer id); //TestEntity get(@Param("id") Integer id); @Insert("INSERT INTO t_test (create_time,modify_time,content)\n" + " VALUES (#{createTime},#{modifyTime},#{content})") int insert(TestEntity TestEntity); @Update("UPDATE t_test SET modify_time=#{modifyTime},content=#{content}\n" + " WHERE id = #{id}") int update(TestEntity TestEntity); @Delete("DELETE FROM t_test WHERE id = #{id}") int delete(Serializable id); @Select("SELECT count(*) FROM t_test") int count(); /** * 根據名稱模糊查詢信息 */ @Select("select id, create_time as createTime, modify_time as modifyTime, content\n" + " from t_test where content like '%${content}%'") List<TestEntity> findByContent(String content); /** * 根據queryVo中的條件查詢用戶 */ @Select("select id, create_time as createTime, modify_time as modifyTime, content\n" + " from t_test where id like #{testEntity.id};") List<TestEntity> findTestByVo(QueryVo vo); }
3、修改主類SimpleMybatisMysqlApp,測試一下
package cn.zc.javapro.database.mybatis; import cn.zc.javapro.database.mybatis.mapper.TestMapper; import cn.zc.javapro.database.mybatis.mapper.TestMapper2; import cn.zc.javapro.database.mybatis.tools.MybatisTools; import cn.zc.javapro.database.mybatis.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; public class SimpleMybatisMysqlApp { public static void main(String[] args) { test3(); } public static void test3() { SqlSession sqlSession; TestMapper2 testMapper2; // MybatisTools mybatisTools = new MybatisTools("mybatis-config.xml"); sqlSession = mybatisTools.openCurrentSqlSession(); //得到 TestMapper 接口的實現類對象,TestMapper 接口的實現類對象由 sqlSession.getMapper(TestMapper.class)動態構建出來 testMapper2 = sqlSession.getMapper(TestMapper2.class); //執行查詢操作,將查詢結果自動封裝成 TestEntity 返回 System.out.println(testMapper2.get(1)); mybatisTools.closeCurrentSqlSession(); } public static void test2() { SqlSession sqlSession; TestMapper testMapper; // MybatisTools mybatisTools = new MybatisTools("mybatis-config.xml"); sqlSession = mybatisTools.openCurrentSqlSession(); //得到 TestMapper 接口的實現類對象,TestMapper 接口的實現類對象由 sqlSession.getMapper(TestMapper.class)動態構建出來 testMapper = sqlSession.getMapper(TestMapper.class); //執行查詢操作,將查詢結果自動封裝成 TestEntity 返回 System.out.println(testMapper.get(1)); mybatisTools.closeCurrentSqlSession(); } public static void test() { SqlSession sqlSession; TestMapper testMapper; sqlSession = MybatisUtils.getCurrentSqlSession(); testMapper = sqlSession.getMapper(TestMapper.class); // System.out.println(testMapper.get(1)); MybatisUtils.closeCurrentSession(); } }
六、自定義的數據源
自定義數據源有兩種寫法;之后需要修改一下 mybatis-config.xml,使得Mybatis識別使用該數據源。
1、我們配置一下自定義的數據源
比如我們自定義數據源整合阿里巴巴的druid數據庫連接池:
方案一:extends DruidDataSourceFactory implements DataSourceFactory
方案二:extends UnpooledDataSourceFactory
方案一:MyDataSource.java
package cn.zc.javapro.database.mybatis.datasource; import com.alibaba.druid.pool.DruidDataSourceFactory; import org.apache.ibatis.datasource.DataSourceFactory; import javax.sql.DataSource; import java.util.Properties; public class MyDataSource extends DruidDataSourceFactory implements DataSourceFactory { protected Properties properties; @Override public void setProperties(Properties properties) { this.properties= properties; } @Override public DataSource getDataSource() { try { return createDataSource(properties); } catch (Exception e) { e.printStackTrace(); } return null; } }
方案二:MyDataSource2.java
package cn.zc.javapro.database.mybatis.datasource; import com.alibaba.druid.pool.DruidDataSource; import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory; import javax.sql.DataSource; public class MyDataSource2 extends UnpooledDataSourceFactory { protected DataSource dataSource; public MyDataSource2() { this.dataSource = new DruidDataSource(); } }
2、修改mybatis-config.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"> <!--新建mybatis配置信息文件mybatis-config.xml--> <!--首先是跟元素--> <configuration> <typeAliases> <!--項目實體類對應的包名--> <package name="cn.zc.javapro.database.mybatis.entity"/> </typeAliases> <!--myql數據庫連接信息--> <!--配置環境 , 選擇一個默認的環境mysql--> <environments default="development"> <!--配置mysql的環境--> <environment id="development"> <!--配置事務--> <transactionManager type="JDBC"/> <!--配置連接池--> <dataSource type="cn.zc.javapro.database.mybatis.datasource.MyDataSource"> <!--<dataSource type="POOLED">--> <!--<property name="driver" value="com.mysql.jdbc.Driver"/>--> <!--<property name="url" value="jdbc:mysql://127.0.0.1:3306/db2021?useSSL=false"/>--> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/db2021?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!--配置實體映射xml路徑--> <mappers> <mapper resource="mapper/Test.xml"></mapper> </mappers> </configuration>
3、編寫測試方法TestDruidDemo.java
package cn.zc.javapro.database.mybatis; import com.alibaba.druid.pool.DruidDataSourceFactory; 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.Reader; public class TestDruidDemo { /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { String resource = "mybatis-config.xml"; // 使用類加載器加載mybatis的配置文件(它也加載關聯的映射文件) Reader reader = Resources.getResourceAsReader(resource); // 構建sqlSession的工廠 SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder() .build(reader,"development"); SqlSession session = sessionFactory.openSession(); System.out.println(session); session = sessionFactory.openSession(); System.out.println(session); DruidDataSourceFactory f; } }
七、配置多數據源
配置多數據源(此數據源非比數據源,此處更偏向於數據庫,或者數據的來源),就是通過不同的配置從不同的數據源中獲取數據。比如MySQL的主庫和從庫(或者讀庫和寫庫),不是一個庫,需要配置兩個數據源。甚至是不同數據庫的數據源,有的來自MySQL、有的來自Oracle等,都需要配置多數據源。
具體如下,我們還是在之前的基礎上進行修改。
比如,我現在要從另一個數據庫獲取數據,這是我就要重新配置一個新的mybatis-mysql-config.xml,他和mybatis-config.xml同一級別,知識不同的配置。
1、配置一個新的mybatis-mysql-config.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"> <!--新建mybatis配置信息文件mybatis-mysql-config.xml--> <!--首先是跟元素--> <configuration> <settings> <!-- #開啟mybatis駝峰式命名規則自動轉換 --> <setting name="mapUnderscoreToCamelCase" value="true" /> </settings> <typeAliases> <typeAlias alias="Integer" type="java.lang.Integer" /> <typeAlias alias="Long" type="java.lang.Long" /> <typeAlias alias="HashMap" type="java.util.HashMap" /> <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" /> <typeAlias alias="ArrayList" type="java.util.ArrayList" /> <typeAlias alias="LinkedList" type="java.util.LinkedList" /> <!--項目實體類對應的包名--> <package name="cn.zc.javapro.database.mybatis.entity"/> </typeAliases> <!--myql數據庫連接信息--> <!--配置環境 , 選擇一個默認的環境mysql--> <environments default="development"> <!--配置mysql的環境--> <environment id="development"> <!--配置事務--> <transactionManager type="JDBC"/> <!--配置連接池--> <dataSource type="cn.zc.javapro.database.mybatis.datasource.MyDataSource"> <!--<dataSource type="POOLED">--> <!--<property name="driver" value="com.mysql.jdbc.Driver"/>--> <!--<property name="url" value="jdbc:mysql://127.0.0.1:3306/db2021?useSSL=false"/>--> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8"/> <property name="username" value="root"/> <property name="password" value="root"/> </dataSource> </environment> </environments> <!-- 映射文件定位 --> <!--這個就是說一下,要執行的sql語句的xml文件在哪,這里可以寫相對路徑也可以寫絕對路徑,絕對路徑就是url,相對路徑使用resource--> <mappers> <!-- <mapper url = "file:Users/zc/MybatisMysqlAnnotation/src/main/resources/mapper/Test.xml" /> --> <!--配置實體映射xml路徑, 配置文件就用這個--> <mapper resource="mapper/User.xml"></mapper> <!-- 注冊Mapper映射接口,注解就用這個--> <!--<mapper class = "cn.zc.javapro.database.mybatis.mapper.UserMapper" />--> </mappers> </configuration>
2、添加一個新的實體類UserEntity.java
package cn.zc.javapro.database.mybatis.entity; import lombok.Data; import java.io.Serializable; @Data public class UserEntity implements Serializable { private int id; // 郵箱 private String email; // 昵稱 private String nickName; // 密碼 private String passWord; // 注冊時間 private String regTime; // 用戶名 private String userName; }
3、添加一個新的Mapper,UserMapper.java
package cn.zc.javapro.database.mybatis.mapper; import cn.zc.javapro.database.mybatis.entity.UserEntity; import java.util.List; public interface UserMapper { List<UserEntity> list(); }
4、添加一個新的配置文件,User.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"> <!--新建實體映射文件 User.xml,這里的namespace就是寫 UserMapper 全類名,否則不能使用動態代理的方式調用接口 UserMapper--> <mapper namespace="cn.zc.javapro.database.mybatis.mapper.UserMapper"> <!--配置 查詢結果的列明和實體類的屬性名的對應關系--> <resultMap id="userMap" type="UserEntity"> <!--主鍵字段的對應 --> <id property="id" javaType="Integer" column="id"></id> <!--非主鍵字段的對應--> <result property="email" javaType="String" column="email"></result> <result property="nickName" javaType="String" column="nick_name"></result> <result property="passWord" javaType="String" column="pass_word"></result> <result property="regTime" javaType="String" column="reg_time"></result> <result property="userName" javaType="String" column="user_name"></result> </resultMap> <select id="list" resultMap="userMap"> SELECT * FROM user </select> <!--<select id="list" resultType="TestEntity"> SELECT * FROM t_test </select>--> <!--<select id="list" resultType="TestEntity"> SELECT id,create_time as createTime,modify_time as modifyTime ,content FROM t_test </select>--> </mapper>
5、修改主類,進行測試
package cn.zc.javapro.database.mybatis; import cn.zc.javapro.database.mybatis.entity.UserEntity; import cn.zc.javapro.database.mybatis.mapper.TestMapper; import cn.zc.javapro.database.mybatis.mapper.TestMapper2; import cn.zc.javapro.database.mybatis.mapper.UserMapper; import cn.zc.javapro.database.mybatis.tools.MybatisTools; import cn.zc.javapro.database.mybatis.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; public class SimpleMybatisMysqlApp { public static void main(String[] args) { System.out.println("------------test3--------------"); test3(); System.out.println("------------test4--------------"); test4(); } public static void test4() { SqlSession sqlSession; UserMapper userMapper; // MybatisTools mybatisTools = new MybatisTools("mybatis-mysql-config.xml"); sqlSession = mybatisTools.openCurrentSqlSession(); //得到 UserMapper 接口的實現類對象,UserMapper 接口的實現類對象由 sqlSession.getMapper(UserMapper.class)動態構建出來 userMapper = sqlSession.getMapper(UserMapper.class); //執行查詢操作,將查詢結果自動封裝成 UserEntity 返回 for(UserEntity userEntity: userMapper.list()) { System.out.println(userEntity); } mybatisTools.closeCurrentSqlSession(); } public static void test3() { SqlSession sqlSession; TestMapper2 testMapper2; // MybatisTools mybatisTools = new MybatisTools("mybatis-config.xml"); sqlSession = mybatisTools.openCurrentSqlSession(); //得到 TestMapper 接口的實現類對象,TestMapper 接口的實現類對象由 sqlSession.getMapper(TestMapper.class)動態構建出來 testMapper2 = sqlSession.getMapper(TestMapper2.class); //執行查詢操作,將查詢結果自動封裝成 TestEntity 返回 System.out.println(testMapper2.get(1)); mybatisTools.closeCurrentSqlSession(); } public static void test2() { SqlSession sqlSession; TestMapper testMapper; // MybatisTools mybatisTools = new MybatisTools("mybatis-config.xml"); sqlSession = mybatisTools.openCurrentSqlSession(); //得到 TestMapper 接口的實現類對象,TestMapper 接口的實現類對象由 sqlSession.getMapper(TestMapper.class)動態構建出來 testMapper = sqlSession.getMapper(TestMapper.class); //執行查詢操作,將查詢結果自動封裝成 TestEntity 返回 System.out.println(testMapper.get(1)); mybatisTools.closeCurrentSqlSession(); } public static void test() { SqlSession sqlSession; TestMapper testMapper; sqlSession = MybatisUtils.getCurrentSqlSession(); testMapper = sqlSession.getMapper(TestMapper.class); // System.out.println(testMapper.get(1)); MybatisUtils.closeCurrentSession(); } }
結果如下:

八、批量插入Insert與批量更新Update
待補充
https://www.cnblogs.com/zhangchao0515/p/14333262.html
參考:
Mybatis中進行批量更新(updateBatch):https://www.cnblogs.com/eternityz/p/12284760.html
Mybatis批量新增和修改:https://blog.csdn.net/lan_qinger/article/details/84138216
MyBatis批量新增數據:https://www.cnblogs.com/shouyaya/p/12797984.html
總結:
1) Mybatis是在 JDBC基礎上進行進一步封裝
2)Mybatis用到了很多設計模式,包括但不限於 工廠模式,建造者模式,代理模式,適配模式(比如MySQL、Oracle等);還用到反射等。
3)Mybatis隱藏了細節,最終肯定要把實體類的成員變量和表的列名一一對應起來。 其中實體類的成員變量通過get方法獲取值,通過set方法設置值。
