本文主要是介绍MyBatis学习笔记-22.1.28,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1- MyBatis简介
1.1-是什么
是apache的一个开源持久层框架,用于数据库的处理
获取MyBatis
-
maven
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.9</version> </dependency>
-
github
1.2-持久化
数据持久化
持久化就是将数据在持久和瞬时转化的过程,也就是从内存-数据库转化的过程。
1.3-持久层
-
完成持久化的代码块
-
界限明显
1.4-Why MyBatis?
- JDBC代码复杂。
- 框架方便自动化
- 用的人多…
- 其实不用也可以
2-Hello MyBatis
2.1-搭建环境
2.1.1-搭建数据库
CREATE TABLE `user`(`id` INT PRIMARY KEY,`name` VARCHAR(30) DEFAULT NULL,`password` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=UTF8;INSERT INTO `user`VALUES
(1,'1','1'),
(2,'2','2'),
(3,'3','3')SELECT * FROM `user`
2.1.2- 新建项目
maven依赖
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.25</version>
</dependency>
<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.9</version>
</dependency>
2.1.3-MyBatis核心配置文件
也就是指示如何连接数据库
dataSource中是具体连接什么数据库
environments可以加入多个environment
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE configurationPUBLIC "-//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://bj-cynosdbmysql-grp-2ny5n7eg.sql.tencentcdb.com:21436/MyBatisLearing?useSSL=true;useUnicode=true;characterEncoding=UTF-8"/><property name="username" value=""/><property name="password" value=""/></dataSource></environment></environments><mappers><!--这里后面再说--><mapper resource="org/mybatis/example/BlogMapper.xml"/></mappers>
</configuration>
2.2-编码部分
2.2.1-编写mybatis工具类
public class MyBatisUtil {//工厂模式,sqlsession的一个工厂static SqlSessionFactory sqlSessionFactory;static{try {String resourse = "MyBatis-config.xml";InputStream inputStream = Resources.getResourceAsStream(resourse);sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);} catch (IOException e) {e.printStackTrace();}}//返回sqlsessionpublic SqlSession getSqlSession(){return sqlSessionFactory.openSession();}
}
2.2.2-编写实体类
同数据库表对应
package com.sunspot.dao;public class User {public int id;public String name;public String password;//省略getter,setter,构造,tostring
}
2.2.3-编写mapper
对应对于一张表的全部操作
对应xxxxDao
package com.sunspot.dao;
import java.util.List;public interface UserMapper {public List<User> getUser();
}
2.2.5-编写mapper的xml
对应xxxxDaoImpl
这里namespace是作用类,id是函数名,resultType是返回类型,值是sql语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sunspot.dao.UserMapper"><select id="getUser" resultType="com.sunspot.dao.User" >select * from MyBatisLearing.user</select>
</mapper>
2.2.6-更改MyBatis-config.xml
这里要把之前编写的mapper添加到MyBatis-config.xml里。
<mappers><mapper resource="com/sunspot/dao/UserMapper.xml"/>
</mappers>
2.2.7-注意maven
maven没有学习,但是大概是maven有个过滤机制,只有满足条件的才会放在最后的项目里,这里我们需要让他将我们写的xxxmapper.xml加入到最后的项目中,
pom.xml加入如下内容
<mappers><mapper resource="com/sunspot/dao/UserMapper.xml"/>
</mappers>
2.3-测试
使用SqlSession.getMapper方法,参数为mapper的接口,返回一个接口,可以通过这个接口进行操作了
看起来,他是利用xxxmapper.xml的配置生成了一个实现接口的实现类,之后将实行类返回了。
public class UserMapperTest {@Testpublic void test1(){MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = myBatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> user = mapper.getUser();for (User user1 : user) {System.out.println(user1);}sqlSession.close();}
}
3- CRUD
3.1-接口
public interface UserMapper {public List<User> getUserList();public User getUser(int id);public int deleteUser(int id);public int updateUser(User user);public int insertUser(User user);
}
3.2-Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sunspot.dao.UserMapper"><select id="getUserList" resultType="com.sunspot.dao.User" >select * from MyBatisLearing.user</select><select id="getUser" resultType="com.sunspot.dao.User" parameterType="int">select * from MyBatisLearing.user where id=#{id}</select><insert id="insertUser" parameterType="com.sunspot.dao.User">insert into MyBatisLearing.user(id, name, password) VALUES (#{id},#{name},#{password})</insert><update id="updateUser" parameterType="com.sunspot.dao.User">update MyBatisLearing.user set name=#{name},password=#{password} where id=#{id}</update><delete id="deleteUser" parameterType="int">delete from MyBatisLearing.user where id=#{id}</delete>
</mapper>
3.3-测试(具体使用)
public class UserMapperTest {@Testpublic void getUserList(){MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = myBatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> user = mapper.getUserList();for (User user1 : user) {System.out.println(user1);}sqlSession.close();}@Testpublic void getUser(){MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = myBatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);User user1 = mapper.getUser(1);System.out.println(user1);}@Testpublic void insertUser(){MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = myBatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);int i = mapper.insertUser(new User(11,"asdasd","wwwwww"));System.out.println(i);sqlSession.commit();//注意sqlSession.close();}@Testpublic void deleteUser(){MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = myBatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);int i = mapper.deleteUser(11);System.out.println(i);sqlSession.commit();//注意sqlSession.close();}@Testpublic void updateUser(){MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = myBatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);int i = mapper.updateUser(new User(2,"222","222"));System.out.println(i);sqlSession.commit();//注意sqlSession.close();}
}
3.4-map处理
接口
public int changePassword(Map<String,Object> map);
mapper
<update id="changePassword" parameterType="map">update MyBatisLearing.userset password = #{newPwd}where id = #{id};
</update>
Test
@Test
public void changePassword(){MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = myBatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);Map<String, Object> map = new HashMap<String,Object>();map.put("newPwd","111113333311111");map.put("id","2");int i=mapper.changePassword(map);System.out.println(i);sqlSession.commit();//注意sqlSession.close();
}
3.5其他SQL技巧
模糊查询
public List<User> searchName(Map<String,Object> map);
<select id="searchName" resultType="com.sunspot.dao.User" parameterType="map">select *from MyBatisLearing.userwhere name like #{value};
</select>
public void testSearchName() {MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = myBatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);Map<String, Object> map = new HashMap<String,Object>();map.put("value","%cao%");List<User> users = mapper.searchName(map);for (User user1 : users) {System.out.println(user1);}sqlSession.close();
}
4-配置解析
4.1-核心配置文件
MyBatis-config.xml
4.2-environments
下有多个environment,可以切换不同数据库,用于测试、上线等等不同情境
4.3-properties
可以直接引入resource里的properties文件。只能放在xml最开始
driver=com.mysql.jdbc.Driver
url=jdbc:mymp;characterEncoding=UTF-8"
username=
password=
<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>
4.4 typeAliases 别名
类型别名,防止冗余
<typeAliases><!--扫描一个包,默认名是小写,但大写也是可以的--><package name="com.sunspot.dao"/><!--单独别名,似乎不可以一起使用--><typeAlias type="com.sunspot.dao.User" alias="user"/>
</typeAliases>
可以在扫描的类加注解设定别名,配合package使用,自动扫描,自动按照注解设置别名
@Alias("Hello")
4.5-Settings
有点用的
- 懒加载
- 缓存
- 驼峰-匈牙利转换
4.6-其他设置
插件
maybatis-plus,在maven仓库可以发现,这个可以进一步拓展。
4.7-映射器
常用方式
- 资源[推荐]
<mappers><mapper resource="com/sunspot/dao/UserMapper.xml"/>
</mappers>
注意这里要用/分割
这里建议全放在resources文件夹下,且包结构一致
- 使用mapper的类名
<mappers><!--<mapper resource="com/sunspot/dao/UserMapper.xml"/>--><mapper class="com.sunspot.dao.UserMapper"/>
</mappers>
要求同名,同包
- 使用包扫描
<mappers><!--<mapper resource="com/sunspot/dao/UserMapper.xml"/>--><!--<mapper class="com.sunspot.dao.UserMapper"/>--><package name="com.sunspot.dao"/>
</mappers>
注意用package而非mapper
也是要求同名同包
4.8-生命周期与作用域
这里是为了并发问题
-
SqlSessionBuilder:用完就扔,局部变量(在工具类里返回SqlSession)
-
SqlSessionFactory: 创建即一直存在,全局唯一。用单例为宜(是工具类的静态变量)
-
SqlSession:不能共享, 用完就关,否则浪费资源。应当放在方法中
-
Mapper:关联一个具体的业务
5-ResultMap结果集映射
如何解决字段名和属性名不一致的问题?
更进一步,复杂的多表查询如何映射?
- 修改sql语句
- 使用结果集映射
使用ReslutMap为数据库列“起别名”
简单的不用使用,但是较复杂的(多表查询等等),可以通过这个映射出来
先看最简单的使用,如何处理字段名属性 名不一致
<resultMap id="rm1" type="Hello"><result column="password" property="psw"/>
</resultMap>
<select id="getUserList" resultMap="rm1">select * from MyBatisLearing.user
</select>
这样就可以将password映射到实体类中的psw属性
具体进一步的见10,
6-日志
6.1-日志工厂
就是排错
Settings里的logImpl里会制定我们的日志软件
- STDOUT_LOGGING 标准日志工厂
- NO_LOGGING 不日志
- LOG4J
使用即可配置
<settings><setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
6.2-Log4j
是什么
一个日志的开源项目
6.2.1-配置
- 导入LOG4J
<dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version>
</dependency>
- log4j.properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=【%c】-%m%n#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/kuang.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=【%p】【%d{yy-MM-dd}】【%c】%m%n#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
- xml
<settings><setting name="logImpl" value="LOG4J"/><!--<setting name="logImpl" value="STDOUT_LOGGING"/>--><!--<setting name="logImpl" value="NO_LOGGING"/>-->
</settings>
**tips:**日志中有DEBUG的信息:xxx类找不到什么的,不用管
[DEBUG][22-01-26][org.apache.ibatis.logging.LogFactory]Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
[DEBUG][22-01-26][org.apache.ibatis.logging.LogFactory]Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
[DEBUG][22-01-26][org.apache.ibatis.io.VFS]Class not found: org.jboss.vfs.VFS
[DEBUG][22-01-26][org.apache.ibatis.io.JBoss6VFS]JBoss 6 VFS API is not available in this environment.
[DEBUG][22-01-26][org.apache.ibatis.io.VFS]Class not found: org.jboss.vfs.VirtualFile
6.2.2-使用
@Test
public void Log4jTest(){Logger logger = Logger.getLogger(UserMapperTest.class);logger.info("info");logger.debug("debug");logger.error("error");
}
[INFO][22-01-26][com.sunspot.dao.UserMapperTest]info
[DEBUG][22-01-26][com.sunspot.dao.UserMapperTest]debug
[ERROR][22-01-26][com.sunspot.dao.UserMapperTest]error
7-分页
减少数据处理量,提高效率
Limit 分页
select * from user limit 0,2
就是跳过0个(从下标0开始查询,所以跳过零个),查询2个
mysql这么用,正常的sql会繁琐一点
select * from user limit 2
省略第一个参数,直接查询2个
public List<User> getUserListByLimit(Map<String,Object> map);
<select id="getUserListByLimit" resultMap="rm1" parameterType="map">select *from MyBatisLearing.userlimit #{startIndex},#{pageCount};
</select>
@Test
public void testGetUserListByLimit() {MyBatisUtil myBatisUtil = new MyBatisUtil();SqlSession sqlSession = myBatisUtil.getSqlSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);Map<String,Object> map=new HashMap<>();map.put("startIndex",0);map.put("pageCount",2);List<User> userListByLimit = mapper.getUserListByLimit(map);for (User user : userListByLimit) {System.out.println(user);}sqlSession.close();
}
8-使用注解开发
在接口上@select等等,会通过反射机制获取返回类型,参数等等,但是只能用简单的sql语句,复杂的不建议使用注解,应当使用xml
在sqlsession实现时也有些问题,应当使用现在不推荐的那些方法
因此这部分不做展开
9-Lombok
获取
- IDEA安装插件
- maven导入
用法
@Getter,@Setter
…在实体类上加,加什么生成什么
@Data
加getter,setter等等很多东西
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {public int id;public String name;public String password;
}
10-resultMap查询进阶
10.1-association处理子类
多表查询,利用resultmap
这里的’多’端含有’一’端的成员对象
JavaType描述子类代替column,之后继续嵌套即可
多 pojo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Son {public int id;public String name;public Father father;
}
一 pojo
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Father {public int id;public String name;
}
mapper接口
public interface SonMapper {public List<Son> getSonAndFather();
}
mapper.xml
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sunspot.mapper.SonMapper"><resultMap id="rm1" type="Son"><result property="id" column="sid"/><result property="name" column="sname"/><association property="father" javaType="Father"><result property="id" column="fid"/><result property="name" column="fname"/></association></resultMap><select id="getSonAndFather" resultMap="rm1">select s.id sid, s.name sname, f.id fid,f.name fnamefrom MyBatisLearing.son s, MyBatisLearing.father fwhere s.fid = f.id;</select>
</mapper>
10.2-collection处理数组
类似上一个,但是使用ofType代替,之后嵌套即可。
11-动态SQL
11.1-if
就是if拼接
这里还有对标switch的choose
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZpYRnjw4-1643370987642)(C:\Users\光球层上的黑子\AppData\Roaming\Typora\typora-user-images\image-20220127210605625.png)]
11.2-trim
解决多and,多逗号等等问题
看起来使用1=1也是可以的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uE04k0Xi-1643370987644)(C:\Users\光球层上的黑子\AppData\Roaming\Typora\typora-user-images\image-20220127210648620.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FvynghXC-1643370987645)(C:\Users\光球层上的黑子\AppData\Roaming\Typora\typora-user-images\image-20220127210706451.png)]
11.3-foreach
就是遍历集合,list,map等等
一般用于 in…子句
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v16Qt6GD-1643370987647)(C:\Users\光球层上的黑子\AppData\Roaming\Typora\typora-user-images\image-20220127210758721.png)]
11-4-bind
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LxuNsOxu-1643370987649)(C:\Users\光球层上的黑子\AppData\Roaming\Typora\typora-user-images\image-20220127210925555.png)]
11.5-sql
就是sql块,可以复用
声明用sql,引用用include
12-缓存
自带两级
默认开一级,是在sqlsession作用域的
可以手动开二级,是namespace作用域
开启方法:全局xml setting(默认开启,但是最好写上),要用的mapper里写<cache/>
这篇关于MyBatis学习笔记-22.1.28的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!