1肥照、第一個Mybatis程序
思路:搭建環(huán)境->導入Mybatis->編寫代碼->測試
1.1搭建環(huán)境
搭建數(shù)據(jù)庫
create database `Mybatis`;
use `mybatis`;
create table `user`(
id int not null,
name varchar(30) default null,
pwd varchar(30) default null,
primary key(`id`)
) ENGINE=INNODB default CHARSET=utf8;
insert into `user`(`id`, `name`, `pwd`)
values(1, 'qwer', '123456'),
(2, 'asdf', '123456'),
(3, 'zxcv', '123456');
新建項目
- ??1.新建一個普通的maven項目
- ??2.刪除src目錄
- ??3.導入maven依賴
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
1.2創(chuàng)建一個模塊
- 編寫mybatis 核心文件
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/Mybatis?useSSL=true&useUnicode=true&charterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root123"/>
</dataSource>
</environment>
</environments>
</configuration>
- 編寫mybatis 工具類
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static{//初始加載
try {
//獲取SqlSessionFactory對象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//有了 SqlSessionFactory,可以從中獲得 SqlSession 的實例蛤袒。
// SqlSession 提供了在數(shù)據(jù)庫執(zhí)行 SQL 命令所需的所有方法。openSession
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
1.3 編寫代碼
- 實現(xiàn)類
public class User {
private int id;
private String name;
private String pwd;
public User() {
}
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
- dao接口
public interface UserDao {
List<User> getUserList();
}
- 接口實現(xiàn) 由DaoImpl轉(zhuǎn)換為了Mapper
<?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.beibei.dao.UserDao">
<select id="getUserList" resultType="com.beibei.pojo.User">
select * from mybatis.user;
</select>
</mapper>
1.4測試
Junit測試
public class UserDemoTest {
@Test
public void test(){
//獲得sqlsession對象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//執(zhí)行sql
UserDao userDao = sqlSession.getMapper(UserDao.class);
List<User> userList = userDao.getUserList();
for (User user :userList) {
System.out.println(user);
}
//關閉sqlsession
sqlSession.close();
}
}
注意點:
錯誤一:org.apache.ibatis.binding.BindingException: Type interface com.beibei.dao.UserDao is not known to the MapperRegistry.
MapperRegistry是什么慈俯?
解決方法:mybatis配置文件中添加
<!--每一個mapper.xml都需要在Mybatis核心配置文件中注冊 斜桿不是.-->
<mappers>
<mapper resource="com/beibei/dao/UserMapper.xml"/>
</mappers>
錯誤二:
java.lang.ExceptionInInitializerError
Could not find resource com.beibei.dao.UserMapper.xml
解決方法:內(nèi)部pom.xml添加
<!--解決資源放在內(nèi)部到逊,導出失敗的問題-->
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
生命周期和作用域
SqlSessionFactoryBuilder->sqlSessionFactory->SqlSession
SqlSessionFactoryBuilder 實例的最佳作用域是方法作用域(也就是局部方法變量):不占用過多資源
SqlSessionFactory 最佳作用域是應用作用域:等同于連接池過多創(chuàng)建影響性能吮便,單例模式
SqlSession 實例不是線程安全的,將 SqlSession 放在一個和 HTTP 請求相似的作用域中镜粤,每次收到 HTTP 請求,就可以打開一個SqlSession,返回一個響應后屏轰,就關閉它僚匆。sqlSession.close();
2. CRUD
??1.namespace
namespace中的包名要和Dao/mapper接口的包名保持一致。
??2.select/insert/update/delete
選擇同规,查詢語句:
- id:對應namespace方法名循狰;
- resultType:Sql語句執(zhí)行返回值窟社!
- parameterType:參數(shù)類型
1.編寫接口
public interface UserDao {
List<User> getUserList();
User getUserByID(int id);
int addUser(User user);
int updateUser(User user);
int deleteUser(int id);
}
2.編寫mapper中的sql語句
<select id="getUserList" resultType="com.beibei.pojo.User">
select * from mybatis.user;
</select>
<select id="getUserByID" resultType="com.beibei.pojo.User" parameterType="int">
select * from mybatis.user where id = #{id};
</select>
<insert id="addUser" parameterType="com.beibei.pojo.User">
insert into mybatis.user(id, name, pwd) values (#{id}, #{name}, #{pwd});
</insert>
<update id="updateUser" parameterType="com.beibei.pojo.User">
update mybatis.user
set name=#{name},
pwd=#{pwd}
where id=#{id};
</update>
<delete id="deleteUser" parameterType="id">
delete from mybatis.user where id = #{id}
</delete>
3.測試 ==注意事務的提交==
@Test
public void testSelectbyID(){
//獲得sqlsession對象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//執(zhí)行sql
UserDao userDao = sqlSession.getMapper(UserDao.class);
User user = userDao.getUserByID(1);
System.out.println(user);
//關閉sqlsession
sqlSession.close();
}
@Test
public void testAddUser(){
//獲得sqlsession對象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//執(zhí)行sql
UserDao userDao = sqlSession.getMapper(UserDao.class);
int res = userDao.addUser(new User(4, "hanhan", "123456"));
System.out.println(res);
//提交事務
sqlSession.commit();
//關閉sqlsession
sqlSession.close();
}
@Test
public void testUpdateUser(){
//獲得sqlsession對象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//執(zhí)行sql
UserDao userDao = sqlSession.getMapper(UserDao.class);
int res = userDao.updateUser(new User(4, "hehe", "123123"));
System.out.println(res);
//提交事務
sqlSession.commit();
//關閉sqlsession
sqlSession.close();
}
@Test
public void testDeleteUser(){
//獲得sqlsession對象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//執(zhí)行sql
UserDao userDao = sqlSession.getMapper(UserDao.class);
int res = userDao.deleteUser(4);
System.out.println(res);
//提交事務
sqlSession.commit();
//關閉sqlsession
sqlSession.close();
}
4.Map妙用
對于字段過多的情況,由于pojo對象的構造方法難以分屬性創(chuàng)建構造方法绪钥,在全屬性構造方法下就必須傳所有參數(shù)灿里,可以使用Map規(guī)避這個問題,只需傳指定參數(shù)即可程腹。
dao:
int updateUserByMap(Map<String, Object> map);
daomapper:
<update id="updateUserByMap" parameterType="map">
update mybatis.user
set name=#{username}
where id=#{id};
</update>
test:
@Test
public void testUpdateUserByMap(){
//獲得sqlsession對象
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao User = sqlSession.getMapper(UserDao.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", 4);
map.put("username", "meng");
int i = User.updateUserByMap(map);
System.out.println(i);
sqlSession.commit();
sqlSession.close();
}
5.模糊查詢
1.Java代碼執(zhí)行的時候匣吊,傳遞通配符%%
List<User> userlist = mapper.getUserLike("%李%");
2.在sql中拼接使用通配符
select * from mybatis.user where name like "%"#{value}"%";
3.配置解析
1.核心配置文件
mybatis-config.xml
properties(屬性)
settings(設置)
typeAliases(類型別名)
typeHandlers(類型處理器)
objectFactory(對象工廠)
plugins(插件)
environments(環(huán)境配置)
environment(環(huán)境變量)
transactionManager(事務管理器)
dataSource(數(shù)據(jù)源)
databaseIdProvider(數(shù)據(jù)庫廠商標識)
mappers(映射器)
- environments(環(huán)境配置)
盡管可以配置多個環(huán)境,但每個 SqlSessionFactory 實例只能選擇一種環(huán)境寸潦。
<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>
- 默認使用的環(huán)境 ID(比如:default="development")色鸳。
- 每個 environment 元素定義的環(huán)境 ID(比如:id="development")。
- 事務管理器的配置(比如:type="JDBC")甸祭。
- 存在JDBC和MANAGED 兩者缕碎,MANAGED一般不用
- 數(shù)據(jù)源的配置(比如:type="POOLED")
- UNPOOLED 無連接池,性能依賴于數(shù)據(jù)庫
- POOLED 存在連接池池户,減少連接響應時間咏雌,可進一步配置
- JNDI EJB 或應用服務器這類容器中使用
2.properties(屬性)
通過properties來實現(xiàn)配置文件引用
編寫db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/Mybatis?useSSL=true&useUnicode=true&charterEncoding=UTF-8
username=root
password=root123
mybatis-config.xml中進行引用
<properties resource="db.properties"/>
3.類型別名(typeAliases)
類型別名可為 Java 類型設置一個縮寫名字。 它僅用于 XML 配置校焦,意在降低冗余的全限定類名書寫赊抖。
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
若有注解,則別名為其注解值寨典。
@Alias("author")
public class Author {
...
}
4.settings(設置)
核心配置:
cacheEnabled:全局性地開啟或關閉所有映射器配置文件中已配置的任何緩存氛雪。默認true
lazyLoadingEnabled: 延遲加載的全局開關。當開啟時耸成,所有關聯(lián)對象都會延遲加載报亩。 特定關聯(lián)關系中可通過設置 fetchType 屬性來覆蓋該項的開關狀態(tài)。默認false
logImpl:指定 MyBatis 所用日志的具體實現(xiàn)井氢,未指定時將自動查找弦追。
完整的配置元素:
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
5.其他配置,基本使用不到
- 類型處理器(typeHandlers)
- objectFactory(對象工廠)
- plugins(插件)
6.其他配置花竞,基本使用不到
MapperRegistry:注冊綁定Mapper文件
方式一:
<!--每一個mapper.xml都需要在Mybatis核心配置文件中注冊-->
<mappers>
<mapper resource="com/beibei/dao/UserMapper.xml"/>
</mappers>
方式二:使用class文件綁定注冊
<mappers>
<mapper class="com.beibei.dao.UserDao"/>
</mappers>
注意點:
?接口和Mapper.xml文件名稱必須一致
?接口和Mapper.xml文件必須在一個包下
方式三:通過包引入
<mappers>
<package name="com.beibei.daoo"/>
</mappers>
注意點:
?接口和Mapper.xml文件名稱必須一致
?接口和Mapper.xml文件必須在一個包下
7.ResultMap結果映射集
當pojo對象與數(shù)據(jù)庫對象字段名稱不相同時劲件,無法正確查詢結果,此時需要使用ResultMap 進行映射
<resultMap id="UserMap" type="com.beibei.pojo.User">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="pwd" column="pasword"/>
</resultMap>
<select id="getUserByID" resultMap="UserMap">
select * from mybatis.user where id = #{id};
</select>
不進行resultType返回约急,使用resultMap進行對象返回
property是數(shù)據(jù)庫字段名
column是pojo屬性
4.日志
如果數(shù)據(jù)庫操作出現(xiàn)異常零远,需要通過日志進行更方便的排錯
在mybatis-config.xml中存在settings進行日志配置
logImpl 指定 MyBatis所用日志的具體實現(xiàn),未指定時將自動查找厌蔽。
核心2種牵辣,STDOUT_LOGGING 和常用的 LOG4J
4.1日志工廠
STDOUT_LOGGING標準的日志工廠實現(xiàn),無需添加外部包奴饮,配置好可直接使用
配置項:
<!--settings放在properties和environments之間-->
<!--標準的日志工廠實現(xiàn)-->
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
輸出結果:
Opening JDBC Connection
Created connection 156545103.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@954b04f]
==> Preparing: select * from mybatis.user where id = ?;
==> Parameters: 1(Integer)
<== Columns: id, name, pwd
<== Row: 1, qwer, 123456
<== Total: 1
User{id=1, name='qwer', password='123456'}
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@954b04f]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@954b04f]
Returned connection 156545103 to pool.
4.2log4j
優(yōu)點:
- 可以通過一個配置文件來靈活地進行配置服猪,而不需要修改應用的代碼
- 日志信息輸送的目的地是控制臺供填、文件、GUI組件罢猪,甚至是套接口服務器近她、NT的事件記錄器、UNIX Syslog守護進程等
- 導入log4j
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
- resources下編寫log4j.properties
當前配置為輸出到文件和控制臺
### 配置根 ###
#日志信息輸出到console和file下
log4j.rootLogger = debug,console,file
### 設置輸出sql的級別膳帕,其中l(wèi)ogger后面的內(nèi)容全部為jar包中所包含的包名 ###
log4j.logger.org.apache=dubug
log4j.logger.java.sql.Connection=dubug
log4j.logger.java.sql.Statement=dubug
log4j.logger.java.sql.PreparedStatement=dubug
log4j.logger.java.sql.ResultSet=dubug
### 配置輸出到控制臺 ###
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = %d{ABSOLUTE} %5p %c{1}:%L - %m%n
### 配置輸出到文件 ###
log4j.appender.file = org.apache.log4j.FileAppender
log4j.appender.file.File = logs/log.log
log4j.appender.file.Append = true
log4j.appender.file.Threshold = DEBUG
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n
3.配置log4j為mybatis日志實現(xiàn)
<!--settings放在properties和environments之間-->
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
4.測試運行
19:31:52,373 DEBUG LogFactory:105 - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
19:31:52,376 DEBUG LogFactory:105 - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
19:31:52,414 DEBUG PooledDataSource:353 - PooledDataSource forcefully closed/removed all connections.
19:31:52,414 DEBUG PooledDataSource:353 - PooledDataSource forcefully closed/removed all connections.
19:31:52,415 DEBUG PooledDataSource:353 - PooledDataSource forcefully closed/removed all connections.
19:31:52,415 DEBUG PooledDataSource:353 - PooledDataSource forcefully closed/removed all connections.
19:31:52,563 DEBUG JdbcTransaction:136 - Opening JDBC Connection
19:31:52,868 DEBUG PooledDataSource:424 - Created connection 793315160.
19:31:52,868 DEBUG JdbcTransaction:100 - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2f490758]
19:31:52,875 DEBUG getUserList:143 - ==> Preparing: select * from mybatis.user;
19:31:52,920 DEBUG getUserList:143 - ==> Parameters:
19:31:52,952 DEBUG getUserList:143 - <== Total: 4
User{id=1, name='qwer', password='123456'}
User{id=2, name='asdf', password='123456'}
User{id=3, name='zxcv', password='123456'}
User{id=4, name='meng', password='123123'}
19:31:52,955 DEBUG JdbcTransaction:122 - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2f490758]
19:31:52,961 DEBUG JdbcTransaction:90 - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@2f490758]
19:31:52,961 DEBUG PooledDataSource:381 - Returned connection 793315160 to pool.
5.log4j項目使用
使用類中引入
import org.apache.log4j.Logger;
具體測試使用
static Logger logger = Logger.getLogger(UserDemoTest.class);
@Test
public void testLog4j(){
logger.info("info: testLog4j");
logger.debug("debug: testLog4j");
logger.error("error: testLog4j");
}
可以在輸出文件logs.log看差異
[ INFO ] - 2020-08-30 19:46:07 info: testLog4j
[ DEBUG ] - 2020-08-30 19:46:07 debug: testLog4j
[ ERROR ] - 2020-08-30 19:46:07 error: testLog4j
5.分頁實現(xiàn)
為什么需要分頁粘捎?
- 減少數(shù)據(jù)處理量
5.1 limit 分頁
limit語法:
mysql> SELECT * FROM table LIMIT 5,10; // 檢索記錄行 6-15
//為了檢索從某一個偏移量到記錄集的結束所有的記錄行,可以指定第二個參數(shù)為 -1:
mysql> SELECT * FROM table LIMIT 95,-1; // 檢索記錄行 96-last.
//如果只給定一個參數(shù)危彩,它表示返回最大的記錄行數(shù)目:
mysql> SELECT * FROM table LIMIT 5; //檢索前 5 個記錄行
//換句話說攒磨,LIMIT n 等價于 LIMIT 0,n。
測試:
創(chuàng)建接口:
List<User> getUserListByLimit(Map<String, Object> map);
mapper:
<resultMap id="UserMap" type="com.beibei.pojo.User">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="pwd" column="pasword"/>
</resultMap>
<select id="getUserListByLimit" parameterType="map" resultMap="UserMap">
select * from mybatis.user limit #{startIndex}, #{pageSize};
</select>
測試調(diào)用:
@Test
public void testSelectByLimit(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao userdao = sqlSession.getMapper(UserDao.class);
Map<String, Object> map = new HashMap<String, Object>();
map.put("startIndex", 0);
map.put("pageSize", 2);
List<User> userList = userdao.getUserListByLimit(map);
for (User user:userList) {
System.out.println(user);
}
sqlSession.close();
}
5.2.RowBounds 分頁
不再使用sql實現(xiàn)分頁汤徽,通過mybatis官方方法實現(xiàn)(不推薦)
接口:
List<User> getUserListByRowBounds();
mapper.xml
<select id="getUserListByRowBounds" resultMap="UserMap">
select * from mybatis.user;
</select>
測試腳本
@Test
public void testSelectByRowBounds(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
RowBounds rowBounds = new RowBounds(1,2 );
List<User> userList = sqlSession.selectList("com.beibei.dao.UserDao.getUserListByRowBounds", null, rowBounds);
for (User user: userList) {
System.out.println(user);
}
sqlSession.close();
}
5.3 其他插件方式
Mysql分頁處理(PageHelper)
6 使用注解開發(fā)
**面向接口編程 **
- 解耦
- 定義(規(guī)范娩缰,約束)與實現(xiàn)(名實分離的原則)的分離。
- 接口的本身反映了系統(tǒng)設計人員對系統(tǒng)的抽象理解
6.1使用注解開發(fā)
1.注解在接口上實現(xiàn)
@Select("select * from mybatis.user")
List<User> getUsers();
2.需要在核心配置中綁定接口
<!--mapper 綁定注解接口-->
<mappers>
<mapper class="beibei.dao.UserDao"/>
</mappers>
3.測試
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUsers();
for (User user: userList ) {
System.out.println(user);
}
sqlSession.close();
}
本質(zhì):反射來獲取注解信息實現(xiàn)
底層:動態(tài)代理
6.2 注解開發(fā)CRUD
6.2.1 自動提交事務
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);//自動提交事務
}
6.2.2 編寫接口
@Insert("insert into mybatis.user(id, name, pwd) values(#{id}, #{name}, #{pwd})")
int addUser(@Param("id") int id, @Param("name") String name, @Param("pwd") String password);
@Update("update mybatis.user set name=#{name} where id = #{id}")
int updateUser(@Param("id") int id, @Param("name") String name);
6.2.3 增加測試類
@Test
public void testAddUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int i = mapper.addUser(5, "qwer", "123321");
System.out.println(i);
}
@Test
public void testUpdateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserDao mapper = sqlSession.getMapper(UserDao.class);
int i = mapper.updateUser(5, "asdf");
System.out.println(i);
}
6.3 #{} 和${} 區(qū)別
{}是預編譯處理谒府,對應JBDC中的PreparedStatement拼坎,可以防止依賴注入。
${}是字符串替換完疫。不能防止依賴注入
7.Lombok
不用再getter setter 構造 toString ,注解即可完成
1.idea安裝插件
2.導入依賴
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
3.使用:
@ToString
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class User {
private int id;
private String name;
private int age;
private String birth;
private Date birthday;
}
@Data:生成無參 get set toString equeals hashcode
@AllArgsConstructor:生成全參
@NoArgsConstructor:生成無參
7 復雜查詢
7.1環(huán)境搭建
1.導入lombok
2.新建實體類Teacher泰鸡、Student
3.建立Mapper接口
4.建立Mapper.xml文件
5.核心配置文件中綁定注冊的Mapper接口或文件
6.測試查詢是否成功
7.2 多對一,多表查詢
方式一:按照查詢嵌套處理
核心mapper配置如下
<select id="getAllStudent" resultMap="student-teacher">
select * from mybatis.student;
</select>
<resultMap id="student-teacher" type="com.beibei.pojo.Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--查詢結果映射到對應的子查詢條件中-->
<association property="teacher" column="tid" javaType="com.beibei.pojo.Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="com.beibei.pojo.Teacher">
select * from mybatis.teacher where id = #{id};
</select>
方式二:按結果嵌套查詢
<select id="getAllStudent2" resultMap="student-teacher2">
select s.id sid, s.name sname,t.name tname from student s, teacher t where t.id = s.tid;
</select>
<resultMap id="student-teacher2" type="com.beibei.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<!--查詢結果映射到對應的子查詢條件中-->
<association property="teacher" javaType="com.beibei.pojo.Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
7.3 一對多壳鹤,集合查詢
<select id="getTeacherbyid" resultMap="teacher-student">
select t.id tid, t.name tname, s.id sid, s.name sname
from student s, teacher t
where t.id = s.tid and t.id = #{tid};
</select>
<resultMap id="teacher-student" type="com.beibei.pojo.Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!--javatype指定屬性的類型盛龄,集合中的泛型信息,使用oftype獲取-->
<collection property="students" ofType="com.beibei.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
8 動態(tài)sql
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
數(shù)據(jù)庫搭建
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) NOT NULL COMMENT '博客標題',
`author` VARCHAR(30) NOT NULL COMMENT '博客作者',
`create_time` DATETIME NOT NULL COMMENT '創(chuàng)建時間',
`views` INT(30) NOT NULL COMMENT '瀏覽量',
primary key(`id`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
pojo對象
@Data
public class Blog {
private String id;
private String title;
private String author;
private Date createTime;
private int views;
}
if判斷動態(tài)語句
mapper
<insert id="addBlog" parameterType="com.beibei.pojo.Blog">
insert into mybatis.blog(id, title, author, create_time, views)
values (#{id}, #{title}, #{author}, #{createTime}, #{views});
</insert>
<select id="queryBlogIF" parameterType="map" resultType="com.beibei.pojo.Blog">
select * from mybatis.blog where 1=1
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
測試
@org.junit.Test
public void testAddBlog(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blog = new Blog();
blog.setAuthor("QWER");
blog.setCreateTime(new Date());
blog.setTitle("QWEQWRT");
blog.setViews(6213);
blog.setId(IDutils.getIdrandom());
int i = mapper.addBlog(blog);
System.out.println(i);
sqlSession.commit();
sqlSession.close();
}
@org.junit.Test
public void testQueryBlogIF(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
map.put("author","QWER");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog.toString());
}
// sqlSession.commit();
sqlSession.close();
}
choose(when otherwise)選擇動態(tài)語句
和java的switch效果相同
mapper:
<select id="queryBlogChoose" parameterType="map" resultType="com.beibei.pojo.Blog">
select * from mybatis.blog where 1=1
<choose>
<when test="title != null">
and title = #{title}
</when>
<when test="title != null and author != null">
and author = #{author}
</when>
<otherwise>
and views > 100
</otherwise>
</choose>
</select>
test:
@org.junit.Test
public void testQueryBlogChoose(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
map.put("author","QWER");
map.put("title", "QWEQWRT");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog.toString());
}
// sqlSession.commit();
sqlSession.close();
}
trim (where, set)
where 是取消where 1=1 使用的芳誓,update中可能使用
trim 則是優(yōu)化多于的and or 余舶,等元素的
==set== 有使用的必要,優(yōu)化update中可能存在的多于","
進行set相關的測試
<update id="updateBlogSet" parameterType="map">
update mybatis.blog
<set>
<if test="author != null">author = #{author},</if>
<!-- 大于小于注意要轉(zhuǎn)換,和尾巴的逗號 -->
<if test="views >= 1000">views = views+1000,</if>
</set>
where 1= 1 and author = "pgm"
</update>
測試:
@org.junit.Test
public void testUpdateBlogSet(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
map.put("author","darmon");
map.put("title", "QWEQWRT");
int i= mapper.updateBlogSet(map);
System.out.println(i);
sqlSession.commit();
sqlSession.close();
}
foreach 集合類條件動態(tài)語句
你可以將任何可迭代對象(如 List锹淌、Set 等)欧芽、Map 對象或者數(shù)組對象作為集合參數(shù)傳遞給 foreach。當使用可迭代對象或者數(shù)組時葛圃,index 是當前迭代的序號,item 的值是本次迭代獲取到的元素憎妙。==當使用 Map 對象(或者 Map.Entry 對象的集合)時库正,index 是鍵,item 是值==
mapper
<select id="queryBlogIn" parameterType="map" resultType="com.beibei.pojo.Blog">
select * from mybatis.blog
where 1=1 and author in
<foreach collection="authors" item="author" index="index"
open="(" separator="," close=")">
#{author}
</foreach>
</select>
測試用例
@org.junit.Test
public void testQueryBlogIn(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
ArrayList<String> authors = new ArrayList<String>();
authors.add("pgm");
authors.add("darmon");
map.put("authors",authors);
List<Blog> blogs = mapper.queryBlogIn(map);
for (Blog blog : blogs) {
System.out.println(blog.toString());
}
sqlSession.commit();
sqlSession.close();
}
9.緩存機制
為了提升查詢效率厘唾,引入了緩存機制
mybatis緩存共定義了2級緩存
一級緩存(本地緩存):
- 默認情況開啟
- 作用于Sqlsession級別(sqlsession.close關閉便關閉)
- 修改數(shù)據(jù)后緩存失效(全刷新褥符,失效)
- sqlsession.clearCache();//清理緩存
二級緩存:
- namespace級別緩存(又叫mapper級別,任意訪問mapper.xml的文件都能使用)
- 主配置文件中必須開啟緩存設置(默認開啟)
<setting name="cacheEnabled" value="true"/>
- 在mapper.xml中添加<cache/>既開啟二級緩存
- 緩存設置(FIFO 緩存(先進先出)抚垃,每隔 60 秒刷新喷楣,最多可以存儲結果對象或列表的 512 個引用趟大,而且返回的對象被認為是只讀的)
- 默認使用LRU算法機制(最近最少使用)
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
- 緩存策略包含
LRU – 最近最少使用:移除最長時間不被使用的對象。
FIFO – 先進先出:按對象進入緩存的順序來移除它們铣焊。
SOFT – 軟引用:基于垃圾回收器狀態(tài)和軟引用規(guī)則移除對象逊朽。
WEAK – 弱引用:更積極地基于垃圾收集器狀態(tài)和弱引用規(guī)則移除對象
存在多級緩存時,查詢調(diào)用順序是== 優(yōu)先二級緩存 ==曲伊,==其次一級緩存==叽讳,==最后查數(shù)據(jù)庫==
Mybatis執(zhí)行流程