一、Mybatis概述
1. 框架简介
目标
- 了解什么是框架
- 理解框架解决的问题
讲解
1.1 什么是框架
框架是整个或部分应用的可重用设计,是可定制化的应用骨架。它可以帮开发人员简化开发过程,提高开发效率。
- 项目里有一部分代码:和业务无关,而又不得不写的代码==>框架
- 项目里剩下的部分代码:实现业务功能需要的逻辑代码
简而言之,框架是一个应用系统的半成品,开发人员在框架的基础上,根据业务需求开发功能。即:别人搭台,你唱戏。
1.2 框架解决了什么问题
框架主要是解决了技术整合问题,实现了项目和具体技术的解耦,提升项目的可维护性
一个应用系统,必定要选用大量的技术来完成业务需求,实现功能。这就导致应用系统依赖于具体的技术,一旦技术发生了变化或者出现问题,会对应用系统造成直接的冲击,这是应该避免的。
框架的出现,解决了这个问题:框架是技术的整合。如果使用了框架,在框架基础上进行开发,那么开发人员就可以直接调用框架的API来实现功能,而不需要关注框架的底层具体使用了哪些技术。这就相当于框架“屏蔽”了具体的技术,实现了应用系统功能和技术的解耦。
框架一般处于低层应用平台(如JavaEE)和高层业务逻辑之间
1.3 有哪些常见的框架
每个框架都是要解决一些具体的问题的,我们可以从JavaEE的三层架构,来说一下常见的框架有哪些。
Mybatis:
-
框架职责:作用在dao层,负责数据库访问的框架。
-
框架介绍:
它原本是Apache的一个开源项目ibatis,后来迁移到了Google code,并改名为Mybatis;之后又迁移到了github上。
它是一个优秀的Java轻量级dao层框架,对JDBC进行了封装,使开发人员只需要关注SQL语句,而不需要关注JDBC的API执行细节。
Hibernate:
-
框架职责:作用在dao层,负责数据库访问的框架。
-
框架介绍:
Hibernate是一个完全面向对象的Dao层框架,封装程度非常高,开发人员可以完全以面向对象的方式操作数据库,甚至不需要编写SQL语句。
但是,正因为Hibernate的封装程度过高,导致它的执行效率受到了影响,是重量级框架。目前在国内使用的越来越少了。
SpringMVC:
-
框架职责:作用在web层,负责和客户端交互的框架。
-
框架介绍:
SpringMVC是Spring Framework的后续产品,受益于Spring框架的流行,并且因为SpringMVC使用简单、和Spring整合简单,导致SpringMVC框架在国内使用的也越来越多。
Struts1/Struts2:
-
框架职责:作用在web层,负责和客户端交互的框架。
-
框架介绍:
Struts1是比较老的框架,目前已经基本不使用了。
Struts2目前使用的也越来越少,逐步被SpringMVC代替
Spring:
- 框架职责:不是作用在某一层,而是实现web层、Service层、Dao层之间解耦的框架,是三层之间的粘合剂
- 框架介绍:Spring框架是为了解决应用开发的复杂性而创建的,任何Java应用都可以从Spring中受益。Spring是一个轻量级控制反转(IOC)和面向切面(AOP)的容器框架。
2. Mybatis简介
目标
- 理解为什么要使用Mybatis
讲解
dao层常用的技术如下图所示:
2.1 JDBC的问题
JDBC是操作数据库的最基本的规范,它的功能简单单一,在使用时需要开发人员处理很多问题:
- 硬编码问题
- 大量的重复代码
- 性能问题
- JavaBean和表数据的映射转换问题
2.2 ORM思想【面试】
ORM:Object Relation Mapping,对象关系映射思想。指把Java对象和数据库的表的字段进行关联映射,从而达到操作Java对象,就相当于操作了数据库。查询了数据库,自动封装成JavaBean对象
- 关系—>对象: 查询表数据,ORM框架自动帮我们把结果封装成JavaBean对象
- 对象—>关系: 插入数据、修改数据等等,ORM框架自动帮我们把JavaBean对象转换成对应的SQL语句
常见的ORM框架:
- Hibernate:是完全ORM框架,实现了双向映射。简单功能更简单,复杂功能更复杂
- 关系—>对象:查询不用写SQL,也不用自己封装JavaBean
- 对象—>关系:DML也不用写DQL
- Mybatis:是半ORM框架,只实现了单向映射
- 关系—>对象:查询不用自己封装JavaBean
- 对象—>关系:没有实现,还需要我们自己编写SQL语句
2.3 Mybatis介绍
Mybatis是一个优秀的Java轻量级持久层框架。apache的ibatis,后来托管到google code,后来又迁移到github上。 Mybatis官网:http://www.mybatis.org/mybatis-3/zh/index.html
- 它内部封装了JDBC,使开发人员只需要关心SQL语句,而不需要处理繁琐的JDBC步骤
- 它采用了ORM思想(半ORM),解决了实体和数据库映射的问题。只要提供好sql语句,配置了映射,Mybatis会自动根据参数值动态生成SQL,执行SQL并把结果封装返回给我们。
- 它支持XML和注解两种方式配置映射。
小结
- ORM:对象-关系映射思想。表示一个JavaBean对象,要对应表里的一行数据。
- 关系->对象的映射:从表里查询数据,由框架帮我们自动封装成JavaBean对象
- 对象->关系的映射:把JavaBean里的数据存储到表里时,由框架帮我们自动把JavaBean的属性值,设置到表里对应的字段上
- Hibernate是一个全ORM框架,实现了双向的自动映射。如果使用Hibernate,简单功能不需要写SQL。复杂功能需要再学习一套HQL语言
- Mybatis是一个半ORM框架,只实现了"关系->对象"的自动映射。如果使用Mybatis框架,需要自己编写SQL
Mybatis
-
JDBC的基本使用:Statement
//1. 注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2. 获取连接 Connection conn = DriverManager.getConnection("jdbc:mysql:///day04","root","root"); //3. 创建SQL执行平台 Statement statement = conn.createStatement(); //4. 执行SQL语句 ResultSet resultSet = statement.executeQuery(String sql); int count = statement.executeUpdate(String sql); boolean isQuery = statement.execute(String sql); //5. 处理结果 while(resultSet.next()){ resultSet.getXxx(列序号); resultSet.getXxx(列名称); } //6. 释放资源 resultSet.close(); statement.close(); connection.close();
-
SQL注入漏洞
通过构造特殊的参数值,可以修改SQL语句的结构,绕过SQL的一些条件
可以使用预编译对象解决SQL注入漏洞
-
JDBC的预编译对象:PreparedStatement
可以解决SQL注入漏洞:更安全
程序可读性更高
同一SQL多次执行时,性能更强
//1. 注册驱动 Class.forName("com.mysql.jdbc.Driver"); //2. 获取连接 Connection conn = DriverManager.getConnection("jdbc:mysql:///day04","root","root"); //3. 创建SQL执行平台 PreparedStatement statement = conn.prepareStatement("select * from user where id = ?"); //4. 执行SQL语句 statement.setInt(1, 1); ResultSet resultSet = statement.executeQuery(); int count = statement.executeUpdate(); boolean isQuery = statement.execute(); //5. 处理结果 while(resultSet.next()){ resultSet.getXxx(列序号); resultSet.getXxx(列名称); } //6. 释放资源 resultSet.close(); statement.close(); connection.close();
-
JDBC事务管理
try{ //1. 注册驱动 //2. 获取连接 //===开启事务=== connection.setAutoCommit(false); //3. 创建SQL执行平台 //4. 执行SQL语句 //5. 处理结果 //===提交事务=== connection.commit(); }catch(Exception e){ //===回滚事务=== }finally{ //6. 释放资源 }
-
连接池
-
为什么要使用连接池:连接可以复用,少量连接就可以支持海量的数据库操作;性能更强
-
JDBC规范规定了,所有连接池都必须实现的接口是:javax.sql.DataSource,获取连接的方法是getConnection()
-
druid连接池的使用
- 导入jar包:数据库驱动包,连接池的包
- 提供配置文件:xxx.properties,放到src下
- 编写代码使用连接池
//1. 创建连接池对象 DataSource ds = DruidDataSourceFactory.createDataSource(properties); //2. 从连接池里获取连接 Connection connection = ds.getConnection(); // 按照JDBC的步骤操作数据库 //最后:释放资源:close()方法的作用是归还到连接池 connection.close();
-
二、快速入门
需求描述
查询所有用户信息,获取用户集合List<User>
准备工作
1 统一开发环境
- 初始化数据库:执行数据库脚本《资料/mybatisdb.sql》
- 准备开发环境:jdk1.8, mysql5.7, idea2018
2 实现步骤
- 创建Java项目,准备JavaBean
- 编写Mybatis的代码,查询所有用户
- 编写测试代码
入门案例
1 创建Java项目,准备JavaBean
1) 创建java项目,导入jar包
2) 创建JavaBean
- 注意:JavaBean里的成员变量,尽量使用包装类,而不是基本数据类型。因为基本数据类型不支持null值
package com.demo.domain;
import java.util.Date;
/**
* 一张表,要创建一个对应的实体类
* 实体类里的属性,要和表里的字段一一对应
* 实体类属性类型,建议使用包装类,而不是基本数据类型
* 建议JavaBean的属性名 和 表的字段名保持一致
*
*/
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
//get/set方法...
//toString方法...
}
2 编写Mybatis的代码,查询所有用户
1) 创建dao接口(映射器)
- 什么是映射器:dao层的接口,叫映射器。不需要实现类
- 映射器的名称:
XXXDao
,XXXMapper
package com.demo.dao;
import com.demo.domain.User;
import java.util.List;
/**
* 使用Mybatis操作数据库的步骤:
* 1. 在dao包里创建一个接口。只要接口,不要实现类;在接口里定义方法
* 这个接口叫“映射器”。XxxDao,XxxMapper
* 2. 给每个接口创建一个xml配置文件:里边要给方法配置SQL语句
* 名称:要和映射器接口名称相同
* 位置:要和映射器接口放在一起
* 3. 创建一个全局配置的xml文件:主要配置数据源
* 名称:随意。习惯性命名为SqlMapConfig.xml。也可以任意命名mybatis.xml
* 位置:建议放到src下
*/
public interface UserDao {
/**
* 查询所有用户,得到List<user>
*/
List<User> queryAll();
}
2) 准备映射文件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">
<!--
mapper标签:表示是给一个映射器接口做配置的
namespace属性:写映射器接口的全限定类名,表示给哪个映射器接口配置的
-->
<mapper namespace="com.itheima.dao.UserDao">
<!--
给映射器接口里每个方法,都要有一个对应的配置===statement
select标签:用于配置查询语句
insert标签:用于配置插入语句
update标签:用于配置修改语句
delete标签:用于配置删除语句
id属性:写方法名
resultType属性:查询结果集里每一行,要封装成什么对象,写全限定类名
-->
<select id="queryAll" resultType="com.itheima.domain.User">
select * from user
</select>
</mapper>
3) 准备Mybatis的日志配置文件
Mybatis支持使用log4j输出执行日志信息,但是需要我们提供log4j的配置文件放在src下:log4j.properties
注意:
- 如果没有log4j.properties,不影响Mybatis的功能,只是没有详细日志而已
- 如果需要日志的话,要把log4j.properties文件放到类路径(src)下。log4j.properties内容如下:
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE, LOGFILE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
4) 准备Mybatis的全局配置文件xml
- 什么是全局配置文件:要使用Mybatis,必须提供的一个核心配置。只需要一个全局配置即可
- 全局配置文件的要求:
- 名称随意,我们这里叫
SqlMapConfig.xml
- 位置随意,我们这里为了方便读取,放到
src
下
- 名称随意,我们这里叫
- 全局配置文件里必须有的配置:
environments
:用于配置数据库环境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>
<!--配置数据源。default:默认要启用的数据库,写对应environment标签的id值-->
<environments default="heima12">
<!--一个environment标签,可以配置一个数据源-->
<environment id="heima12">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis12?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
<!--<environment id="abc">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///day04?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>-->
</environments>
<!--所有映射xml文件的位置-->
<mappers>
<!--写xml文件的路径。每个xml都要用一个mapper标签配置进来。-->
<mapper resource="com/itheima/dao/UserDao.xml"/>
</mappers>
</configuration>
3 编写测试代码
package com.demo;
import com.demo.dao.UserDao;
import com.demo.domain.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.Test;
import java.io.InputStream;
import java.util.List;
/**
* 测试UserDao的功能
*/
public class UserDaoTest {
@Test
public void testStart() throws Exception {
//1. 加载配置文件
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
//2. 得到一个SqlSession对象:
//使用SqlSessionFactoryBuilder构造一个SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
//使用SqlSessionFactory生产一个SqlSession对象
SqlSession session = factory.openSession();
//3. 获取UserDao代理对象;使用UserDao代理对象操作数据库
UserDao userDao = session.getMapper(UserDao.class);
List<User> userList = userDao.queryAll();
userList.forEach(System.out::println);
//4. 释放资源
session.close();
is.close();
}
}
Mybatis使用步骤
准备工作:导入jar包,创建JavaBean
使用Mybatis的步骤:
- 先创建dao层的接口(映射器):只要接口,不要实现类。名称通常是:XxxDao, XxxMapper
- 给每个dao接口创建一个xml文件(映射配置文件,映射文件):给接口里的方法配置SQL语句
- 创建全局配置的xml文件:名称随意,位置建议放在src下。主要是配置数据源
三、单表CURD
目标
能够使用Mybatis实现单表的curd操作:
- 查询全部用户,得到
List<User>
- 根据主键查询一个用户,得到
User
- 查询数量
- 保存用户(新增用户)
- 修改用户
- 删除用户
- 模糊查询
准备
-
实体类User:略
-
映射器接口UserDao:
package com.itheima.dao; import com.itheima.domain.User; import java.util.List; /** * 如果你的Mybatis环境已经搭建环境,编写功能时,只需要: * 1. 在dao接口里写方法 * 2. 在接口配置文件里写SQL语句 * * 功能需求: * - 查询全部 * - 根据主键查询一个用户,得到`User` * - 查询数量 * - 保存用户(新增用户) * - 修改用户 * - 删除用户 * - 模糊查询 * @author liuyp * @date 2021/09/05 */ public interface UserDao { List<User> queryAll(); }
-
映射配置文件UserDao.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"> <mapper namespace="com.itheima.dao.UserDao"> <select id="queryAll" resultType="com.itheima.domain.User"> select * from user </select> </mapper>
-
单元测试类
在单元测试类中准备好@Before、@After的方法代码备用。
后续要测试一个功能,就增加一个@Test方法即可。
package com.demo; import com.demo.dao.UserDao; import com.demo.domain.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.Date; import java.util.List; /** * Junit的注解: * 1. @Test:加在方法上,方法可以直接运行。要求方法必须是public, void, 无参 * 2. @Before:加在方法上,这个方法会在每个Test方法执行之前,先执行一次 * 3. @After:加在方法上,这个方法会在每个Test方法执行之后,再执行一次 * * 增删改查功能测试 */ public class CurdTest { private UserDao userDao; private SqlSession session; private InputStream is; @Test public void testQueryAll(){ List<User> userList = userDao.queryAll(); for (User user : userList) { System.out.println(user); } } /** * ctrl + alt + f:把选中的变量,提取成Field(成员变量) * ctrl + alt + v:把选中的内容,提取成一个Variable(变量) * ctrl + alt + m:把选中的内容,提取成一个Method(方法) */ @Before public void init() throws IOException { //1. 先加载全局配置文件 is = Resources.getResourceAsStream("SqlMapConfig.xml"); //2. 再得到一个SqlSession对象。这个对象一定是随用随取,用完就关,一定要关 SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is); session = factory.openSession(); //3. 可以获取dao接口的代理对象 userDao = session.getMapper(UserDao.class); } @After public void destroy() throws IOException { //4. 释放资源 session.close(); is.close(); } }
实现
3.1 根据主键查询一个用户
- 在映射器UserDao里加方法
/**
* 根据主键查询一个用户
* @param id 用户id
* @return 得到`User`
*/
User findById(Integer id);
- 在映射文件UserDao.xml里加statement配置
<!--
select标签:用于配置查询语句
id:方法名称
parameterType:参数的类型,可省略不写
resultType:查询结果集中,每一行数据要封装成什么对象,写全限定类名
SQL语句的写法:
Mybatis里的SQL语句,如果有参数,不能写?,要写成 #{}
SQL语句中#{}用于取参数值
如果只有一个参数并且是简单类型,SQL语句里要取参数值,写:#{随意写}
简单类型:8种基本数据类型及包装类, String
-->
<select id="findById" resultType="com.itheima.domain.User">
select * from user where id = #{abc}
</select>
- 功能测试:在测试类里加测试方法
@Test
public void testFindById(){
User user = userDao.findById(41);
System.out.println(user);
}
3.2 查询数量(聚合函数)
- 在映射器UserDao里加方法
/**
* 查询数量
* @return user表里的总数量
*/
int count();
- 在映射文件UserDao.xml里配置statement
<select id="count" resultType="int">
select count(*) from user
</select>
- 功能测试,在单元测试类里加测试方法
@Test
public void testCount(){
int count = userDao.count();
System.out.println("user表的数据量:" + count);
}
3.3 保存/新增用户
- 在映射器UserDao里加方法
/**
* 保存用户(新增用户)
* @param user 要保存的用户信息对象
*/
void save(User user);
- 在映射文件UserDao.xml里配置statement
<!--
使用insert标签配置insert语句
如果方法有查询参数,标签上要加parameterType,写参数的全限定类名。
但是这个属性可以省略;如果省略了,Mybatis会自动推断参数类型
如果参数是JavaBean,SQL语句里取参数值: #{JavaBean的属性名}
如果要插入数据之后,得到最新的主键值,直接修改配置文件即可:
在insert标签里增加子标签selectKey
resultType:查询得到的主键值是什么类型的
keyProperty:查询得到的主键值,要存储到JavaBean对象哪个属性上,写属性名
order:要在insert之前查询主键值,还是在insert之后查询主键值
MySql数据库,要求是AFTER
Oracle数据库,要求是BEFORE
-->
<insert id="save" parameterType="com.itheima.domain.User">
<selectKey resultType="int" keyProperty="id" order="AFTER">
select last_insert_id()
</selectKey>
INSERT INTO USER (username, birthday, sex, address)
VALUES (#{username}, #{birthday}, #{sex}, #{address})
</insert>
- 在测试类里加测试方法
@Test
public void testSave(){
User user = new User();
user.setUsername("4哥");
user.setSex("男");
user.setAddress("宿迁");
user.setBirthday(new Date());
int i = userDao.save(user);
System.out.println("影响行数:" + i);
//注意:使用Mybatis执行完DML操作之后,一定要提交事务
session.commit();
//要求:插入数据之后,可能够得到新数据的id值
System.out.println("保存后:" + user);
}
- 注意:
- SQL语句里
#{JavaBean的属性名}
- 执行完DML语句,不要忘记提交事务
- 如果插入数据时要获取最新的主键值,就在insert里增加子标签selectKey
- SQL语句里
3.4 修改用户
- 在映射器接口里加方法
/**
* 修改用户
* @param user 要修改的用户信息
*/
void edit(User user);
- 在映射文件里配置statement
<update id="edit" parameterType="com.itheima.domain.User">
UPDATE USER SET
username = #{username},
birthday = #{birthday},
sex = #{sex},
address = #{address}
WHERE id = #{id}
</update>
- 在测试类里添加测试方法
@Test
public void testEdit(){
User user = userDao.findById(50);
user.setSex("女");
user.setUsername("2姐");
userDao.edit(user);
session.commit();
}
- 注意事项:
- 执行了DML语句,需要提交事务
sqlSession.commit()
- SQL语句里使用
#{JavaBean的属性名}
- 执行了DML语句,需要提交事务
3.5 删除用户
- 在映射器接口里加方法
/**
* 删除用户
* @param id 要删除的用户id
*/
void delete(Integer id);
- 在映射文件UserDao.xml里配置statement
<delete id="delete" parameterType="int">
delete from user where id = #{abc}
</delete>
- 在测试类里增加测试方法
@Test
public void testDelete(){
userDao.delete(50);
session.commit();
}
- 注意事项:
- 执行完DML语句,需要提交事务
sqlSession.commit()
- SQL语句里: 只有一个参数并且是简单类型,
#{随便写}
- 执行完DML语句,需要提交事务
3.6 模糊查询
1 使用#{}
方式进行模糊查询
- 在映射器UserDao里加方法
/**
* CURD功能-模糊查询。
* 使用#{}方式
*/
List<User> search(String username);
-
在映射文件UserDao.xml里配置statement
利用了MySql的特殊拼接字符串的语法
select '%' '王' '%'
,得到的结果是'%王%'
select "%"'王'"%"
,得到的结果是'%王%'
<select id="search" parameterType="String" resultType="User">
select * from user where username like "%"#{abc}"%"
</select>
- 在测试类里加测试方法
@Test
public void testSearch(){
List<User> list = userDao.search("王");
for (User user : list) {
System.out.println(user);
}
}
2 使用${}
方式进行模糊查询
- 在映射器接口里加方法
/**
* CURD功能-模糊查询
* 使用${}方式
*/
List<User> search2(String username);
- 在映射文件UserDao.xml里配置statement
<select id="search2" parameterType="String" resultType="User">
select * from user where username like '%${value}%'
</select>
- 在测试类里加测试方法
@Test
public void testSearch(){
// List<User> list = userDao.search("王");
List<User> list = userDao.search2("王");
for (User user : list) {
System.out.println(user);
}
}
3 #{}
和${}
的区别
#{}
:本质是预编译方式执行SQL- 可以防止SQL注入漏洞
- 如果只有一个参数,并且是简单类型,
#{}
里边可以随意写#{abc}
- Mybatis会自动进行Java类型和JDBC类型的转换
${}
:本质是拼接SQL语句字符串- 不能防止SQL注入漏洞
- 如果只有一个参数,并且是简单类型,
${}
只能写成value
===>${value}
(最新版本Mybatis里也可以随便写,但是仍然建议写成${value}
) - 不会进行Java类型和JDBC类型转换。Mybatis会把参数值
toString()
后,直接拼接到SQL语句里
有错误大家指正,共同进步,共同学习。