UserDao
/**
* 根据id查询
*/
User findUserById(Integer id);
xml代码
<select id="findUserById" parameterType="java.lang.Integer" resultType="com.atguigu.pojo.User">
select * from user where id = #{id}
select>
测试代码
@Test
public void testFindUserById(){
User user = userDao.findUserById(48);
System.out.println(user); // User{id=48, username=小马宝莉, password='96543'}
}
核心配置文件.xml 添加日志
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
打印结果
在日志初始化的时候,使用标准输出
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.log4j:
打开JDBC的链接
Opening JDBC Connection
创建链接
Created connection 1020155847.
设置自动提交false
Setting autocommit to false on JDBC Connection
[com.mysql.cj.jdbc.ConnectionImpl@3cce57c7]
执行SQL语句
==> Preparing: select * from user where username like ?
==> Parameters: %李%(String)
<== Columns: id, password, username, birthday
<== Row: 42, 456, 李四, null
<== Total: 1
执行结果
User{id=42, password=456, username='李四'}
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3cce57c7]
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3cce57c7]
执行完毕之后,把链接对象返回到连接池
Returned connection 1020155847 to pool.
UserDao代码
/**
* 模糊查询
*/
List<User> findUserByName(String name);
模糊查询有两种实现方式
第一种实现方式 使用#{} xml代码
<select id="findUserByName" parameterType="string" resultType="com.atguigu.pojo.User">
select * from user where username like #{username}
select>
测试代码
@Test
public void testFindUserByName(){
// 第一种实现方法 sql中不需要添加sql 传递的参数需要加上%
List<User> users = userDao.findUserByName("%李%");
for (User user : users) {
System.out.println(user);
}
}
第二种实现方式 使用${} xml代码
测试代码
@Test
public void testFindUserByName(){
// 第二种实现方法 在sql中添加% 传递的参数不需要加%
List<User> users = userDao.findUserByName("李");
for (User user : users) {
System.out.println(user);
}
}
${}:字符串连接 字符串替换 UserDao代码
/**
* 使用mybatis的替换
* 如果有多个参数,二个或两个以上参数就必须使用这个注解 注解里面的参数建议跟形参保持一致
* @param columName
* @param columValue
* @return
*/
List<User> findByNameOrPassword(@Param("columName") String columName, @Param("columValue") String columValue);
xml代码
<select id="findByNameOrPassword" resultType="com.atguigu.pojo.User">
select * from user where ${columName} like concat('%', #{columValue}, '%')
select>
测试代码
// 通过username或password进行查找
@Test
public void testFindByNameOrPassword(){
// 使用username进行查找
// List userList = userDao.findByNameOrPassword("username", "李");
// 使用password进行查找
List<User> userList = userDao.findByNameOrPassword("password", "9");
for (User user : userList) {
System.out.println(user);
}
}
注意:${} 除了拼接和替换以外 其他所有的地方 都必须使用#{}
UserDao代码
/**
* 查询总用户数
*/
int findTotal();
xml代码
<select id="findTotal" resultType="int">
select count(*) from user
select>
测试代码
// 测试查询总记录条数
@Test
public void testFindTotal(){
int total = userDao.findTotal();
System.out.println(total); // 10
}
创建QueryVo类
package com.atguigu.pojo;
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
UserDao代码
List<User> findByVo(QueryVo vo);
xml代码
<select id="findByVo" resultType="com.atguigu.pojo.User" parameterType="com.atguigu.pojo.QueryVo">
select * from user where username like #{user.username}
select>
测试代码
@Test
public void testFindByQueryVo(){
QueryVo queryVo = new QueryVo();
User user = new User();
user.setUsername("%李%");
queryVo.setUser(user);
List<User> users = userDao.findByVo(queryVo);
for (User user1 : users) {
System.out.println(user1);
}
}
新建User2类
package com.atguigu.pojo;
public class User2 {
private Integer id;
private String userName;
private String pass_word;
@Override
public String toString() {
return "User2{" +
"id=" + id +
", userName='" + userName + '\'' +
", pass_word='" + pass_word + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPass_word() {
return pass_word;
}
public void setPass_word(String pass_word) {
this.pass_word = pass_word;
}
}
UserDao代码
List<User2> findAll2();
xml代码
<resultMap id="userMap" type="com.atguigu.pojo.User2">
<id column="id" property="id">id>
<result column="username" property="userName">result>
<result column="password" property="pass_word">result>
resultMap>
<select id="findAll2" resultMap="userMap">
select * from user
select>
测试代码
@Test
public void testFindAll(){
List<User2> user2List = userDao.findAll2();
for (User2 user2 : user2List) {
System.out.println(user2);
}
}
作用:降低冗余
在核心配置文件里面设置别名
<typeAliases>
<package name="com.atguigu.pojo"/>
typeAliases>
之后在xml配置文件里面 写参数类型 或者写返回值类型可以直接写对象的名称
<mapper namespace="com.atguigu.dao.UserDao">
<select id="findAll" resultType="user">
select * from user
select>
mapper>
需要在核心配置文件里面获取数据源
<properties resource="jdbc.properties">properties>
在资源配置文件resources下面创建jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
jdbc.username=root
jdbc.password=123456
修改核心配置文件
<dataSource type="POOLED">
<property name="username" value="${jdbc.username}">property>
<property name="password" value="${jdbc.password}">property>
mybatis中数据源的配置
测试数据源:
我们的数据源配置就是在SqlMapConfig.xml文件中,具体配置如下:
MyBatis在初始化时,解析此文件,根据 的type属性来创建相应类型的的数据源DataSource,即:
type=”POOLED”:MyBatis会创建PooledDataSource实例

结论:它是从池中获取一个连接来用。
type=”UNPOOLED” : MyBatis会创建UnpooledDataSource实例

结论:它是每次创建一个新的连接来用。
所以我们使用连接池的技术会节省连接资源。
JDBC 中事务的回顾
在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法就可以调整。
通过 JDK 文档,我们找到该方法如下:

那么我们的 Mybatis 框架因为是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的
setAutoCommit()方法来设置事务提交方式的。
Mybatis 中事务的提交方式,本质上就是调用 JDBC 的 setAutoCommit()来实现事务控制。
我们运行之前所写的代码:
@Test
public void testProxyDao() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
//获得MyBatis框架生成的UserMapper接口的实现类
UserDao userMapper = sqlSession.getMapper(UserDao.class);
User user = userMapper.findById(41);
System.out.println(user);
sqlSession.close();
}

通过上面的研究和分析,现在我们一起思考,为什么 CUD 过程中必须使用 sqlSession.commit()提交事
务?主要原因就是在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法,这样我们
就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法实现事务提
交。
明白这一点后,我们现在一起尝试不进行手动提交,一样实现 CUD 操作。注释手动提交事物

我们发现,此时事务就设置为自动提交了,同样可以实现CUD操作时记录的保存。虽然这也是一种方式,但就
编程而言,设置为自动提交方式为 false 再根据情况决定是否进行提交,这种方式更常用。因为我们可以根据业务
情况来决定提交是否进行提交。
Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。
我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,
如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。
① 创建工程:
mabatis-dynamic-sql
②添加pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>org.examplegroupId>
<artifactId>day44mybatis-dynamic-sqlartifactId>
<version>1.0-SNAPSHOTversion>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.6version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.16version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
dependencies>
project>
③导入基本配置:
拷贝这五个文件到项目
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oeXfnoTW-1667721726513)(C:/Users/ZZC/AppData/Roaming/Typora/typora-user-images/image-20221106153354214.png)]
④在UserDao接口中 添加查询条件的方法
package com.atguigu.dao;
import com.atguigu.pojo.User;
import java.util.List;
public interface UserDao {
/**
* 根据条件动态设置sql
*/
List<User> findByCondition(User user);
}
⑤UserDao.xml
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.dao.UserDao">
<select id="findByCondition" parameterType="user" resultType="user">
select * from user where 1=1
<if test="id!=null">
and id=#{id}
if>
<if test="username!=null">
and username=#{username}
if>
<if test="password!=null">
and password=#{password}
if>
select>
mapper>
测试文件代码
package com.atguigu;
import com.atguigu.dao.UserDao;
import com.atguigu.pojo.User;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class MybatisTest {
private UserDao userDao;
private SqlSession sqlSession;
private InputStream is;
@After
public void after() throws Exception{
// 提交事务
sqlSession.commit();
// 释放资源
sqlSession.close();
is.close();
}
@Before
public void before() throws IOException {
// 1.需要找到核心配置文件
is = Resources.getResourceAsStream("sqlMapConfig.xml");
// 2.构建会话工厂
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 3.读取核心配置文件里面的io流
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
// 4.获取会话对象
sqlSession = sqlSessionFactory.openSession();
// 5.通过会话工厂 获取userdao对象
userDao = sqlSession.getMapper(UserDao.class);
}
@Test
public void testFindByCondition(){
User user = new User();
user.setId(43);
user.setUsername("王安石");
user.setPassword("123123");
List<User> userList = userDao.findByCondition(user);
for (User user1 : userList) {
System.out.println(user1);
}
}
}
where 1 = 1,永远为真
where 1=1; 这个条件始终为True,在不定数量查询条件情况下,1=1可以很方便的规范语句。