mybatis的学习笔记,看的是狂神的视频
mybatis
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。mybatis是一个优秀的基于java的持久层框架,设计目的就是让我们对执行SQL语句时对输入输出的数据管理更加方便
不用Mybatis也可以,更容易上手,技术没有高低之分
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.24version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.6version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
dependencies>
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
properties>
<typeAliases>
<typeAlias type="com.jinx.pojo.User" alias="User"/>
<package name="com.jinx.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>
<environment id="test">
<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&userUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
<mappers>
<package name="com.jinx.dao"/>
mappers>
configuration>
mysql8.0及以上的driver需要改为com.mysql.cj.jdbc.Driver
amp;为转义字符
package com.jinx.utils;
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.IOException;
import java.io.InputStream;
//sqlSessionFactory
public class MybatisUtils {
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//使用Mybatis第一步:获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
//SqlSession完全包含了面向数据库执行SQL命令所需的所有方法
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
-实体类User
package com.jinx.pojo;
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;
}
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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
public interface UserDao {
List<User> getUserList();
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jinx.dao.UserDao">
<select id="getUserList" resultType="com.jinx.pojo.User">
select * from mybatis.user;
select>
mapper>
package com.jinx.dao;
import com.jinx.utils.MybatisUtils;
import com.jinx.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
public class UserDaoTest {
@Test
public void test() {
//第一步获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();
//方式一:getMapper
// UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// List userList = mapper.getUserList();
//方式二:
List<User> userList = sqlSession.selectList("com.jinx.dao.UserMapper.getUserList");
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
}
<mappers>
<package name="com.jinx.dao"/>
mappers>
注册mappers的两种方式
<build>
<resources>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.xmlinclude>
<include>**/*.propertiesinclude>
includes>
resource>
<resource>
<directory>src/main/resourcesdirectory>
<includes>
<include>**/*.xmlinclude>
<include>**/*.propertiesinclude>
includes>
resource>
resources>
build>
namespace要和Dao/mapper接口的类名一致,从而绑定
<mapper namespace="com.jinx.dao.UserMapper">
User getUserById(@Param("id")int id);
@Param(“id”) 里面的id对应着xxxMapper.xml中sql语句的#{id}
<select id="getUserById" parameterType="int" resultType="com.jinx.pojo.User">
select * from mybatis.user where id = #{id};
select>
@Test
public void getUserByID() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(1);
System.out.println(user);
sqlSession.close();
}
<insert id="addUser" parameterType="com.jinx.pojo.User">
insert into mybatis.user(id, name, pwd) values (#{id},#{name},#{pwd});
insert>
<update id="updateUser" parameterType="com.jinx.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>
增删改需要提交事务
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession(true);
}
int addUser2(Map<String, Object> map);
<insert id="addUser2" parameterType="map">
insert into mybatis.user(id, name, pwd) values (#{userid},#{userName},#{passWord});
insert>
此处的#{userid},#{userName},#{passWord}可以随便起名
public void addUser2() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Object> map = new HashMap<>();
map.put("userid",5);
map.put("userName",5);
map.put("passWord",5);
mapper.addUser2(map);
sqlSession.commit();
sqlSession.close();
}
只要测试类中put到map集合中的键值对的键名对应即可
Map传递参数,直接在sql中取出key即可!【parameterType=“map”】
对象传递参数,直接在sql中取对象的属性即可【parameterType=“Object”】
只有一个基本类型参数情况下,可以不写parameterType
多个参数用map,或者注解
List<User> userList = mapper.getUserLike("%张%");
select * from mybatis.user where name like "%"#{value}"%";
configuration(配置)
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
mybatis默认的事务管理器是JDBC(2个),连接池:POOLED(3个)
我们可以通过properties属性来实现引用配置文件
编写db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&userUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
username=root
password=123456
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
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>
<typeAliases>
<typeAlias type="com.jinx.pojo.User" alias="User"/>
typeAliases>
<typeAliases>
<package name="com.jinx.pojo"/>
typeAliases>
实体类少用第一种
实体类多用第二种
第一种可以diy别名,第二种不行
也可以在实体类上增加注解
@Alias("hello")
public class User {}
<mappers>
<mapper resource="com/jinx/dao/UserMapper.xml"/>
mappers>
<mappers>
<mapper class="com.jinx.dao.UserMapper"/>
mappers>
注意点
<mappers>
<package name="com.jinx.dao"/>
mappers>
SqlSessionFactoryBuilder
SqlSessionFactory
SqlSession
public class User {
private int id;
private String name;
private String password;
}
public interface UserMapper {
User getUserById(@Param("id") int id);
}
<select id="getUserById" parameterType="int" resultType="user">
select id,name,pwd as password from mybatis.user where id = #{id};
select>
<resultMap id="UserMap" type="user">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
resultMap>
<select id="getUserById" parameterType="int" resultMap="UserMap">
select * from mybatis.user where id = #{id};
select>
result元素是MyBatis中最重要最强大的元素
ResultMap的设计思想是,对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了
ResultMap
的优秀之处——你完全可以不用显式地配置它们。
如果世界总是这么简单就好了
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.17.1version>
dependency>
新建一个log4j.properties放到resources目录下
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/jinx.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
<settings>
<setting name="logImpl" value="LOG4J"/>
settings>
在要使用的类中导入包import org.apache.log4j.Logger;
日志对象,参数为当前类的class
static Logger logger = Logger.getLogger(UserDaoTest.class);
logger.info("info进入了testLog4j");
logger.debug("debug进入了testLog4j");
logger.error("error进入了testLog4j");
List<User> getUserLimit(Map<String, Object> map);
<select id="getUserLimit" parameterType="map" resultType="User">
select * from mybatis.user limit #{startIndex},#{pageSize};
select>
public void getUserByLimit() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("startIndex",0);
map.put("pageSize",2);
List<User> userList = mapper.getUserLimit(map);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
List<User> getUserRowBounds();
<select id="getUserRowBounds" resultType="User">
select * from mybatis.user ;
select>
public void getUserByRowBounds() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
RowBounds rowBounds = new RowBounds(1, 2);
List<User> userList = sqlSession.selectList("com.jinx.dao.UserMapper.getUserRowBounds",null,rowBounds);
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
@Select("select * from user")
List<User> getUsers();
<mappers>
<mapper class="com.jinx.dao.UserMapper"/>
mappers>
public void test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUsers();
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();
}
@Select("select * from user")
List<User> getUsers();
@Select("select * from user where id = #{id}")
User getUserById(@Param("id") int id);
@Insert("insert into user (id,name,pwd) values (#{id},#{name},#{password})")
int addUser(User user);
@Update("update user set name = #{name},pwd=#{password} where id =#{id}")
int updateUser(User user);
@Delete("delete from user where id =#{uid}")
int deleteUser(@Param("uid") int id);
#{}不会被注入,安全
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.18.22version>
dependency>
常用的注解
@Data//无参构造
@AllArgsConstructor//有参构造
@EqualsAndHashCode
@NoArgsConstructor//无参构造
@ToString
@Getter
多个学生对应一个老师
@Data
public class Student {
private int id;
private String name;
//学生需要关联一个老师
private Teacher teacher;
}
@Data
public class Teacher {
private int id;
private String name;
}
<select id="getStudent" resultMap="StudentTeacher">
select * from mybatis.student;
select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
resultMap>
<select id="getTeacher" resultType="Teacher">
select * from mybatis.teacher where id =#{tid}
select>
<select id="getStudent2" resultMap="StudentTeacher2">
select s.tid stid ,s.id sid,s.name sname,t.name tname from mybatis.student s,mybatis.teacher t where s.tid = t.id;
select>
<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="stid"/>
association>
resultMap>
注意stid 在teacher
一个老师对应多个学生
@Data
public class Student {
private int id;
private String name;
private int tid;
}
@Data
public class Teacher {
private int id;
private String name;
private List<Student> students;
}
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid, s.name sname, t.name tname, t.id tid
from mybatis.student s,
mybatis.teacher t
where s.tid = t.id and t.id = #{tid}
select>
<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"/>
<result property="tid" column="tid"/>
collection>
resultMap>
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from mybatis.teacher where id = #{tid};
select>
<resultMap id="TeacherStudent2" type="Teacher">
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id">collection>
resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from mybatis.student where tid = #{tid};
select>
1.关联-association【多对一】
2.集合-collection【一对多】
3.javaType & ofType
javaType 实体类属性类型
ofType 用来指定映射到List或者集合中的pojo类型,泛型中的约束类型
注意点:
动态 SQL 是 MyBatis 的强大特性之一
<select id="queryBlogIF" parameterType="map" resultType="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 id="queryBlogChoose" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<choose>
<when test="title != null">
title = #{title}
when>
<when test="author != null">
author = #{author}
when>
<otherwise>
and views = #{views}
otherwise>
choose>
where>
select>
<select id="queryBlogIF" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<if test="title != null">
title =#{title}
if>
<if test="author != null">
and author = #{author}
if>
where>
select>
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},if>
<if test="password != null">password=#{password},if>
<if test="email != null">email=#{email},if>
<if test="bio != null">bio=#{bio}if>
set>
where id=#{id}
update>
所谓的动态SQL本质还是SQL语句,只是我们可以在SQL层面执行一些逻辑代码
<sql id="if1">
<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 mybatis.blog
<where>
<include refid="if1">include>
where>
select>
注意事项
List<Blog> queryBlogForeach(Map map);
<select id="queryBlogForeach" parameterType="map" resultType="Blog">
select * from mybatis.blog
<where>
<foreach collection="ids" item="id" open="and (" separator="or" close=")">
id = #{id}
foreach>
where>
select>
public void queryBlogForeach() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap<>();
ArrayList<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
//用map往进传list
map.put("ids",ids);
List<Blog> blogs = mapper.queryBlogForeach(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
动态sql就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了
建议:先写SQL,然后再对应的修改成为动态SQL
SqlSession
一级缓存默认开启,只在一次SqlSession中有效,也就是拿到连接到关闭连接这个区间
一级缓存相当于一个map
工作机制
<setting name="cacheEnabled" value="true"/>
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true">
cache>
小结:
<dependency>
<groupId>org.mybatis.cachesgroupId>
<artifactId>mybatis-ehcacheartifactId>
<version>1.2.1version>
dependency>
<cache type="org.mybatis.caches.ehcache.EhcacheCache">cache>
<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>
君子慎独,不欺暗室,含章可贞,卑以自牧