- 简介
- 第一个MyBatis
- 搭建环境
- CRUD
- mybatis-config.xml标签
- environment
- properties
- typeAliases
- mappers注册
- 生命周期和作用域
- 属性≠字段
- log
- STDOUT_LOGGING
- LOG4J
- 分页
- limit
- RowBounds
- 使用注解开发
- Lombok
- 多对一association
- 法一:查询嵌套
- 法二:结果嵌套(直接sql,推荐)
- 一对多collection
- 动态SQL
- if
- where
- choose
- set
- sql标签
- foreach
- 缓存
- 一级缓存
- 二级缓存
- 缓存原理
- 自定义缓存ehcatch
MyBatis(原名iBatis)是持久层框架。主要是与数据库打交道
- -避免JDBC和返回集合代码。利用xml文件 *** 作。
maven仓库
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.9version>
dependency>
- dao数据持久化:data access object就是将数据库中的数据,转化为持久状态
- maven导包mysql-connector-java,mybatis
- 主配置文件,并注册mappers
- 实体类、其接口和响应的映射.xml(实现sql *** 作)
- 编写utils,MyTest
- maven导
- pojo
public class User {
private int id;
private String name;
private String pwd;
public User() {
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
- 方法和映射配置文件
public interface UserMapper {
public List<User> selectUser(); //所有用户
public User getUserById(int id);
public int addUser(User user);
public int upDateUser(User user);
public int deleteUser(int id);
int addUser2(Map<String,Object> map);
List<User> getUserLike(String value);
}
================UserMapper.xml===========================
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.adair.dao.UserDao"> //链接UserDao
<select id="selectUser" resultType="com.adair.pojo.User">// 其中的方法,和返回值
select * from mybatis.user
select>
<select id="getUserById" parameterType="int" resultType="com.adair.pojo.User">
select * from mybatis.user where id= #{id}
select>
<insert id="addUser" parameterType="com.adair.pojo.User">
insert into mybatis.user (id,name,pwd) value (#{id},#{name},#{pwd});
insert>
<update id="upDateUser" parameterType="com.adair.pojo.User">
update mybatis.user
set name=#{name},pwd=#{pwd}
where id=#{id};
update>
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id=#{id}
delete>
<insert id="addUser2" parameterType="map">
insert into mybatis.user (id,pwd) values (#{userid},#{passWord})
insert>
<select id="getUserLike" parameterType="String" resultType="com.adair.pojo.User">
select * from mybatis.user where name like #{value}
select>
mapper>
- 主配置文件mybatis-config.xml
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.adair.pojo"/>
typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"/>
<property name="username" value="root"/>
<property name="password" value="123"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/adair/dao/UserMapper.xml"/>
mappers>
configuration>
- MyTest
public class MyTest {
public static void main(String[] args) throws IOException {
String resources = "mybatis-config.xml"; //可以设置为常用类。utils包
InputStream is = Resources.getResourceAsStream(resources);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sessionFactory.openSession(true);
//方式一:getMapper得到类
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.selectUser();//所有用户
User user = mapper.getUserById(1);//id为1
mapper.addUser(new User(5, "zhaoliu", "444"));//增加一个用户
mapper.upDateUser(new User(5,"laowu","555")); //更新用户
mapper.deleteUser(5);
//若数据库没有更变sqlSession.commit();
System.out.println(user.toString());
//方式二:直接得到方法,并利用方法
// List userList = sqlSession.selectList("com.adair.dao.UserDao.selectUser");
HashMap<String, Object> map = new HashMap<>();//new hashmap然后put键值对
map.put("userid",4);
map.put("passWord","444");
mapper.addUser2(map);
List<User> userList = mapper.getUserLike("%李%");
for (User user : userList) {
System.out.println(user.toString());
}
}
}
- utils下的工具类
public class MybatisUtils {//直接优化成工具类
private static SqlSessionFactory sqlsessionFactory;
static {
try {
String resources = "mybatis-config.xml";
InputStream is = Resources.getResourceAsStream(resources);
sqlsessionFactory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e){
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlsessionFactory.openSession();
}
}
传参总结:
- 一个基本类型:直接可以用。标签内无parameterType也可以
- 对象:直接利用属性即可
- map:多个属性,可以利用parameterType=“map”。键值对
- transactionManager
- dataSource
==============db.properties================
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
==============mybatis-config.xml================
<configuration>
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="pwd" value="123"/>
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="${pwd}"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/adair/dao/UserMapper.xml"/>
mappers>
configuration>
typeAliases
自定义。扫描包。注解(在类上)
<typeAliases>
<typeAlias type="com.adair.pojo.User" alias="User"/>
<package name="com.adair.pojo"/>
typeAliases>
@Alias("hello")
public class User {
private int id;
private String name;
private String pwd;
}
======================UserMapper.xml========================
<select id="selectUser" resultType="user">
select * from mybatis.user
select>
mappers注册
法一:通过资源引用。
<mappers>
<mapper resource="com/adair/dao/UserMapper.xml"/>
mappers>
法二:(同一包下。类名同.xml名字一样)
<mappers>
<mapper class="com.adair.dao.UserMapper"/>
mappers>
法三:(要求同二)
<mappers>
<package name="com.adair.dao"/>
mappers>
生命周期和作用域
sqlSessionFactoryBuilder:
- 局部变量,创建sqlSessionFactory就可以挂了。
sqlSessionFactory:
- 应用作用域,运行期间一直存在。相当于一个连接池
sqlSession:
- 方法作用域(用完就关)。连接到连接池的一个请求。sqlSession的实例是不安全的,不可被共享。
tip:代码正确(还报错),删除target下的。
属性≠字段在java类的属性中会出现和数据库字段名字不同的情况(password≠pwd)。
解决方案:
- 别名。在select时,给数据库字段起一个别名(同java属性)
<select id="getUserById" parameterType="int" resultType="com.adair.pojo.User">
select id,name,pwd as password from mybatis.user where id= #{id}
select>
- resultMap
<resultMap id="UserMap" type="User">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
resultMap>
<select id="getUserById" resultMap="UserMap">
select * from mybatis.user where id= #{id}
select>
log
STDOUT_LOGGING
- mybatis-config.xml
<settings> //在MyTest会自动运行,并显示
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
- 控制台
- mybatis-config.xml
<settings> //在MyTest会自动运行,并显示
<setting name="logImpl" value="LOG4J"/>
settings>
- 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/adair.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
- MyTest
static Logger logger = Logger.getLogger(MyTest.class);
@Test
public void test(){
logger.info("info:进入logger");
logger.debug("debug:进入logger");
logger.error("error:进入logger");
}
- 在项目下,自动生成log/adair.log文件
- 在sql
select * from user limit 0,2
- 接口和映射配置文件
public interface UserMapper {
List<User> getUserByLimit(Map<String,Object> map);
}
=======================================================
<select id="getUserByLimit" parameterType="map" resultType="user">
select * from user limit #{startIndex},#{pageSize}
</select>
=======================================================
public static void main(String[] args) throws IOException {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("startIndex",1);
map.put("pageSize",2);
List<User> userList = mapper.getUserByLimit(map);
for (User user : userList) {
System.out.println(user);
}
}
RowBounds
- 借用getUser方法(之前的)得到所有用户
RowBounds rowBounds = new RowBounds(1, 2);
List list = sqlSession.selectList("com.adair.dao.UserMapper.getUser", null, rowBounds);
for (User user : list) {
System.out.println(user);
}
使用注解开发
- UserMapper接口的方法
@Select("select * from mybatis.user where id=#{id}")
public User getUserById(int id);
- 主配置文件用mappers注册就好了
<mappers>
<mapper class="com.adair.dao.UserMapper"/>
mappers>
- MyTest。同上
本质:反射机制。底层:动态代理
- Debug查看本质
-
Mybatis执行流程
-
利用注解select,param
@Select("select * from mybatis.user where id=#{id1}")
public User getUserById(@Param("id1") int id);
- 没有提交到数据库的情况
sqlsessionFactory.openSession(); //设置为true
//或者,手动提交
sqlSession.commit();
-
#{}和${}的区别是什么
a、#{}是预编译处理,${}是字符串替换。
b、Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的 set 方法来赋值;
c、Mybatis 在处理${}
时,就是把${}
替换成变量的值。
d、使用#{}可以有效的防止 SQL 注入,提高系统安全性
偷懒神器
步骤:
- 在idea安装plugin
- 导入maven依赖
- 在类上加注解即可
@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@EqualsAndHashCode
public class User {
private int id;
private String name;
private String pwd;
}
多对一association
法一:查询嵌套
- 导入数据库student ,teacher
- pojo类。用lombok的话,安装插件和库
@Data
public class Student {
private int id;
private String name;
private Teacher teacher;
}
- dao
public interface StudentMapper {
public List<Student> getStudent();
}
- mybatis-config.xml
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
//其他的
<mappers> //导入资源
<mapper class="com.adair.dao.StudentMapper"/>
<mapper class="com.adair.dao.TeacherMapper"/>
mappers>
configuration>
- resources下的com.adair.dao。联表查询
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.adair.dao.StudentMapper">
<select id="getTeacher" resultType="teacher">
select * from teacher
select>
<resultMap id="StudentTeacher" type="student">
<association property="teacher" column="id" javaType="Teacher" select="getTeacher"/>
resultMap>
<select id="getStudent" resultMap="StudentTeacher">
select * from student
select>
mapper>
- 测试查询
- pojo
public interface StudentMapper {
public List<Student> getStudent();
public List<Student> getStudent2();
}
- StudentMapper.xml。assciation用的javaType
<mapper namespace="com.adair.dao.StudentMapper">
<resultMap id="StudentTeacher2" type="student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
<result property="id" column="tid"/>
association>
resultMap>
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.name tname
from student s,teacher t
where s.tid=t.id
select>
mapper>
一对多collection
- List getTeacher();方法。 colletion中的ofType
<resultMap id="TeacherStudent" type="teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
collection>
resultMap>
<select id="getTeacher" resultMap="TeacherStudent">
select t.name tname,t.id tid,s.name sname,s.id sid
from student s,teacher t
where s.tid=t.id
select>
- List getTeacher2();方法。按查询嵌套
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from teacher
select>
<resultMap id="TeacherStudent2" type="Teacher">
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudent" column="id"/> //column也可为name
resultMap>
<select id="getStudent" resultType="student">
select * from student
select>
动态SQL
动态SQL就是根据不同的情况,生成不同的SQL语句
实验
- utils包
public class IDUtils {
public static String getId(){
return UUID.randomUUID().toString().replace("-","");
}
}
- 配置文件
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0/EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties"/>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
settings>
<typeAliases>
<package name="com.adair.pojo"/>
typeAliases>
<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 class="com.adair.dao.BlogMapper"/>
mappers>
configuration>
- 实体类,接口方法,其映射的.xml
===============pojo=================
public class Blog {
private String id;
private String title;
private String author;
private Date createTime;
private int views;
}
=============dao层BlogMapper===================
public interface BlogMapper {
int addBlog(Blog blog);
List<Blog> queryBlogIf(Map<Object, Object> map);
}
if
==============BlogMapper.xml==================
where
- 上面的if在一定条件下会报错(and多余错误) 。where标签可以避免
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<if test="title != null">
title = #{title}
if>
<if test="author != null">
and author = #{author}
if>
where>
select>
choose
- choose(when,otherwise)。相当于switch
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<choose>
<when test="title != null">
title = #{title}
when>
<when test="author != null">
author = #{author}
when>
<otherwise>
views = #{views}
otherwise>
choose>
where>
select>
set
- set标签,会动态的去掉逗号
<update id="updateBlog" parameterType="map">
update blog
<set>
<if test="title != null">
title = #{title},
if>
<if test="author != null">
author = #{author}
if>
set>
<where>
id = #{id}
where>
update>
sql标签
- 使用公共部分的sql语句
<sql id="if-title-author">
<if test="title != null">
title = #{title}
if>
<if test="author != null">
and author = #{author}
if>
sql>
<select id="queryBlogIf" parameterType="map" resultType="blog">
select * from blog
<where>
<include refid="if-title-author">include>
where>
select>
- 注意:片段基于单表。片段不包括where标签
<select id="queryBlogForeach" parameterType="map" resultType="blog">
select * from blog
<where>
<foreach collection="ids" item="id" open="(" close=")" separator=" or ">
id=#{id}
foreach>
where>
select>
public void test1() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap<Object, Object> map = new HashMap<>();
ArrayList<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
map.put("ids",ids);
for (Blog blog : mapper.queryBlogForeach(map)) {
System.out.println(blog);
}
}
缓存
读写分离,主从复制
一级缓存也叫本地缓存
public class MyTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.getUserById(2);
System.out.println(user1);
User user2 = mapper.getUserById(2);
System.out.println(user2);
System.out.println(user1 == user2);
sqlSession.close();
}
}
- 结果
- 在其中增加一个update,更新语句,则会更新缓存。地址不同则会false
- 在两个查询语句中间加入
sqlSession.clearCache();
小结:一级缓存默认开启,只在一次qlSession中有效。
二级缓存也叫全局缓存。由于一级缓存太低,所有诞生了二级缓存。
- 主配置文件
<setting name="cacheEnabled" value="true"/>
- 类配置文件。注意:类要实现序列化
<cache readOnly="true"/> //true为同一个实体类。为fals则是一个拷贝的
<select id="getUserById" resultType="user" useCache="true">
select * from user where id=#{id}
select>
- MyTest
public class MyTest {
public static void main(String[] args) {
SqlSession sqlSession = MybatisUtils.getSqlSession();
SqlSession sqlSession2 = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user1 = mapper.getUserById(1);
System.out.println(user1);
sqlSession.close();
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
User user2 = mapper2.getUserById(1);
System.out.println(user2);
System.out.println(user1 == user2);
sqlSession2.close();
}
}
- 结果
- 查看顺序:用户 → 二级缓存 → 一级缓存 → 数据库
- 提示: 一级缓存提交或关闭之后,才会提交到二级缓存中。不关闭则不提交
- 接口映射的配置文件
- ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<diskStore path="./tmpdir/Tmp_EhCache"/>
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="259200"
memoryStoreEvictionPolicy="LRU"/>
<cache
name="cloud_user"
eternal="false"
maxElementsInMemory="5000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LRU"/>
ehcache>
面试高频:
-
MySql引擎
-
InnoDB底层原理
-
索引
-
索引优化
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)