MyBatis
熟悉MyBatis
jar包:
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
由于maven中约定大于配置(配置文件需要写在resources目录下),所以要配置资源导出:
<!--在build中配置resource,来防止我们资源导出失败的问题-->
<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>
编写工具类:
package com.hitenine.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 --> sqlSession
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();
}
}
//既然有了 SqlSessionFactory,顾名思义,
// 我们就可以从中获得 SqlSession 的实例了。
// SqlSession 完全包含了面向数据库执行 SQL 命令所需的所有方法。
public static SqlSession getSqlSession() {
return sqlSessionFactory.openSession();
}
}
配置文件:
注意xml配置中的顺序:
properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?
<?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核心配置文件-->
<configuration>
<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>
<!-- 每一个Mapper.xml都需要在MyBatis核心配置文件中注册!注意"/"-->
</environments>
<mappers>
<mapper resource="com/hitenine/dao/UserMapper.xml"/>
</mappers>
</configuration>
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8
username=root
password=123456
实体类:
package com.hitenine.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 + '\'' +
'}';
}
}
写接口:
package com.hitenine.dao;
import com.hitenine.pojo.User;
import java.util.List;
public interface UserDao {
List<User> getUserList();
}
写mapper.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">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.hitenine.dao.UserDao">
<!--id为方法名 返回类型:SQL语句的返回值-->
<select id="getUserList" resultType="com.hitenine.pojo.User">
select * from mybatis.user
</select>
</mapper>
使用Junit测试,文件目录最好与src下一样:
package com.hitenine.dao;
import com.hitenine.pojo.User;
import com.hitenine.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserDaoTest {
@Test
public void test() {
//第一步:获得SqlSession对象
SqlSession sqlSession;
sqlSession = MybatisUtils.getSqlSession();
//执行SQL 方式一:getMapper 官方推荐!!
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserList();
//方式二: 不推荐
// List<User> userList = sqlSession.selectList("com.hitenine.dao.UserDao.getUserList");
for (User user : userList) {
System.out.println(user);
}
//关闭SqlSessoin
sqlSession.close();
}
/*
官方建议这样做
//第一步:获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();;
try {
//执行SQL 方式一:getMapper 官方推荐!!
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserList();
//方式二: 不推荐
// List<User> userList = sqlSession.selectList("com.hitenine.dao.UserDao.getUserList");
for (User user : userList) {
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭SqlSessoin
sqlSession.close();
}
*/
}
Mybatis中的CRUD
package com.hitenine.dao;
import com.hitenine.pojo.User;
import java.util.List;
import java.util.Map;
public interface UserMapper {
//查询用户
List<User> getUserList();
//根据id查询用户
User getUserById(int id);
//插入用户
int addUser(User user);
//用map添加
int addUser2(Map<String, Object> map);
//修改任我
int updateUser(User user);
//删除用户
int deletUser(int id);
}
<?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">
<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.hitenine.dao.UserMapper">
<!-- id为方法名 返回类型为:com.hitenine.pojo.User-->
<select id="getUserList" resultType="com.hitenine.pojo.User">
select * from mybatis.user
</select>
<select id="getUserById" parameterType="int" resultType="com.hitenine.pojo.User">
select * from mybatis.user where id = #{id}
</select>
<!-- 对象中的属性可以直接取出来-->
<insert id="addUser" parameterType="com.hitenine.pojo.User">
insert into mybatis. user(id, name, pwd) values (#{id}, #{name},#{pwd});
</insert>
<insert id="addUser2" parameterType="map">
insert into mybatis. user(id, name, pwd) values (#{userid}, #{username},#{password});
</insert>
<update id="updateUser" parameterType="com.hitenine.pojo.User">
update mybatis.user set name = #{name}, pwd = #{pwd} where id = #{id};
</update>
<!--参数类型为int的时候可以不写-->
<delete id="deletUser" parameterType="int">
delete from mybatis.user where id = #{id};
</delete>
</mapper>
package com.hitenine.dao;
import com.hitenine.pojo.User;
import com.hitenine.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class UserMapperTest {
// @Test
public void test() {
//第一步:获得SqlSession对象
SqlSession sqlSession;
sqlSession = MybatisUtils.getSqlSession();
//执行SQL 方式一:getMapper 官方推荐!!
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserList();
//方式二: 不推荐
// List<User> userList = sqlSession.selectList("com.hitenine.dao.UserDao.getUserList");
for (User user : userList) {
System.out.println(user);
}
//关闭SqlSessoin
sqlSession.close();
}
/*
官方建议这样做
//第一步:获得SqlSession对象
SqlSession sqlSession = MybatisUtils.getSqlSession();;
try {
//执行SQL 方式一:getMapper 官方推荐!!
UserDao mapper = sqlSession.getMapper(UserDao.class);
List<User> userList = mapper.getUserList();
//方式二: 不推荐
// List<User> userList = sqlSession.selectList("com.hitenine.dao.UserDao.getUserList");
for (User user : userList) {
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//关闭SqlSessoin
sqlSession.close();
}
*/
//@Test
public void getUserByIdTest() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUserById(3);
System.out.println(user);
sqlSession.close();
}
//增删改需要提交事务
// @Test
public void addUserTest() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int res = mapper.addUser(new User(5, "hah", "123"));
if (res > 0) {
System.out.println("插入成功!");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
//增删改需要提交事务
@Test
public void addUser2Test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("userid", 5);
map.put("username", "hello");
map.put("password", "12345");
mapper.addUser2(map);
//提交事务
sqlSession.commit();
sqlSession.close();
}
//修改用户
//@Test
public void updateUserTest() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int updateUser = mapper.updateUser(new User(4, "哈哈", "1234"));
if (updateUser > 0) {
System.out.println("更新成功!");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
//删除用户
@Test
public void deletUserTest() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int i = mapper.deletUser(4);
if (i > 0) {
System.out.println("删除成功!");
}
//提交事务
sqlSession.commit();
sqlSession.close();
}
}
Map的强大
//用map添加
int addUser2(Map<String, Object> map);
<insert id="addUser2" parameterType="map">
insert into mybatis. user(id, name, pwd) values (#{userid}, #{username},#{password});
</insert>
public void addUser2Test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("userid", 5);
map.put("username", "hello");
map.put("password", "12345");
mapper.addUser2(map);
//提交事务
sqlSession.commit();
sqlSession.close();
}
熟练掌握Map
Map传递参数,直接在sql中取出key即可! parameterType="map"
对象传递参数,直接在sql中取对象的属性即可 parameterType="Object"
只有一个基本类型参数的情况下,可以直接在sql中取到 parameterType可以忽略
多个参数用Map,或注解
模糊查询:
-
java代码执行的时候,传递通配符% %
List<User> userLike = mapper.getUserLike("%h%"); -
在sql拼接中使用通配符
select * from mybatis.user where name like "%"#{value}"%";<select id="getUserByLike" resultType="userDto"> select * from hi_test02.t_user <where> <if test="username != null"> username like concat('%', #{username} ,'%') </if> limit #{offset},#{limit} </where> </select>
ResultMap结果集映射
<!--结果集映射-->
<resultMap id="UserMap" type="User">
<!--column数据库中的字段,property实体类中的属性-->
<!--<result column="id" property="id"/>-->
<!--<result column="name" property="name"/>-->
<result column="pwd" property="password"/>
</resultMap>
<!--可以省略resultType-->
<select id="getUserById" resultMap="UserMap">
select * from mybatis.user where id = #{id}
</select>
日志
注意xml顺序,大小写,是否多空格
日志工厂:
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
Log4j:
-
先导入log4j的jar包<!--
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> -
log4j.properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和life的定义在下面的代码 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/hitenine.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 -
配置log4j为日志的实现
<settings> <setting name="logImpl" value="LOG4J"/> </settings> -
Log4j的使用,直接测试
简单使用
-
在要使用Log4j 的类中,导入org.apache.log4j.Logger;
-
日志对象,加载参数为当前类的class
static Logger logger = Logger.getLogger(UserDaoTest.class); -
日志级别
logger.info("info:进入了testLog4j方法"); logger.debug("debug:进入了testLog4j"); logger.error("error:进入了testLog4j");
多对一处理
按照查询嵌套处理
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性我们需要单独处理
对象:association
集合:collection
-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id}
</select>
按照结果嵌套处理
<select id="getStudent2" resultMap="StudentTeacher2">
select 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"/>
</association>
</resultMap>
一对多处理
按照查询嵌套处理
<select id="getTeacher" resultMap="TeacherStudent">
select s.id sid, s.name sname, t.name tname, t.id tid
from student s,
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"/>
<!--复杂的属性,我们需要处理 对象:association 集合:collection
javaType="" 指定属性的类型
集合中的泛型信息,我们使用ofType获取
-->
<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">
<!--<result property="id" column="id"/>-->
<!--<result property="name" column="name"/>-->
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select * from mybatis.student where tid = #{tid}
</select>
驼峰命名转换
creat_time -- > creatTime
<setting name="mapUnderscoreToCamelCase" value="true"/>
动态SQL
什么事动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句
利用动态SQL这一特性可以彻底摆脱这种痛苦
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
搭建环境
CREATE TABLE `bolg`(
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) not null comment '博客标题',
`author` VARCHAR(30) not null comment '博客作者',
`creat_time` datetime not null comment '创建时间',
`views` int(30) not null comment '浏览量'
)ENGINE=InnoDB DEFAULT CHARSET=utf8
创建一个基础工程
-
导包
-
编写配置文件
-
编写实体类
@Data public class Blog { private int id; private String title; private String author; private Date creatTime; private int views; } -
编写实体类对应的Mapper接口和Mapper.xml
IF
<select id="queryBlogIF" parameterType="map" resultType="com.rui.pojo.Blog">
select * from mybatis.bolg where 1=1
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</select>
@Test
public void queryBlogIF(){
SqlSession sqlSession = MyBatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap map = new HashMap();
map.put("author","尹锐");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog blog : blogs) {
System.out.println(blog);
}
sqlSession.close();
}
choose (when, otherwise)
<select id="queryBlogChoose" parameterType="map" resultType="com.rui.pojo.Blog">
select * from mybatis.bolg
<where>
<choose>
<when test="title != null">
title=#{title}
</when>
<when test="author!=null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
trim, (where, set)
select * from mybatis.bolg
<where>
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
<update id="updateBlog" parameterType="map">
update mybatis.bolg
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author},
</if>
</set>
where id = #{id}
</update>
所谓的动态SQL,本质还是SQL语句,只是我们可以在SQL层面,去执行一些逻辑代码
if
Where,set,choose,when
SQL片段
有的时候,我们可能会将一些公共的部分抽取出来,方便复用!
-
使用SQL标签抽取公共的部分
<sql id="if-title-author"> <if test="title != null"> title = #{title} </if> <if test="author != null"> and author = #{author} </if> </sql> -
在需要使用的地方使用Include标签引用即可
<select id="queryBlogIF" parameterType="map" resultType="com.rui.pojo.Blog"> select * from mybatis.bolg <where> <include refid="if-title-author"></include> </where> </select>注意事项:
- 最好基于单表来定义SQL片段!
- 不要存在where或者set标签,片段里尽量只有if就好了
Foreach
select * from user where 1=1 and <foreach item="id" index="index" collection="ids" open="(" separator="or" close=")"> #{id} </foreach> (id=1 or id=2 or id=3)<!-- select * from mybatis.bolg where 1=1 and (id=1 or id=2 or id=3) 我们现在传递一个万能的map,这个map中可以存在一个map --> <select id="queryBlogForeach" parameterType="map" resultType="com.rui.pojo.Blog"> select * from mybatis.bolg <where> <foreach collection="ids" item="id" open="(" close=")" separator="or"> id = #{id} </foreach> </where> </select>动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了
建议:
- 先在Mysql中写出完整的SQL,在对应的去修改称为我们的动态SQL
foreach
<delete id="deleteUser" parameterType="list">
delete from hi_test02.t_user where id in
<if test="list!=null and list.size()>0">
<foreach collection="list" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</if>
</delete>

浙公网安备 33010602011771号