MyBatis 增删改查 CRUD
MyBatis 增删改查 CRUD
1. 查询
根据上次所说,实体类
和工具类
不需要变了!我们只需要变的是UserMapper.java
、UserMapper.xml
、UserMapperTest.java
(测试类)
步骤
- 编写接口
- 编写对应的mapper中的sql语句
- 测试
注意点:
增删改查,需要提交事务!
UserMapper.xml
文件可以放在resources
文件夹中!
sql语句 insert 、update、delete 返回值默认情况下是int类型 :matched(匹配的)行数
如果要返回:changed(受影响的)行数
只需在mysql数据连接url参数加useAffectedRows=true
例如:jdbc.url=jdbc:mysql://localhost:3306/ssm?useAffectedRows=true
- 编写接口
UserMapper.java
//根据ID查询用户
User getUserById(int id);
-
编写对应的mapper中的sql语句
UserMapper.xml
-
namespace
中的包名要和Dao/mapper 接口的包名一致!
<mapper namespace="com.guo.dao.UserMapper"> <!--绑定-->
-
select
选择,查询语句id
就是对应的namespace
中的方法名resultType
: sql语句执行的返回值parameterType
:参数类型
<select id="getUserById" parameterType="int" resultType="com.guo.pojo.User">
select * from mybatis.user where id = #{id}
</select>
- 测试
UserMapperTest.java
(测试类)
@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(); // 不变
}
2. 增加 insert
UserMapper.java
//insert一个用户
int addUser(User user);
UserMapper.xml
<!--对象中的属性,可以直接取出来-->
<insert id="addUser" parameterType="com.guo.pojo.User" >
insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
</insert>
UserMapperTest.java
(测试类)
增删改需要提交事物
//增删改需要提交事物
@Test
public void addUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();//不变
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//不变
int res = mapper.addUser(new User(4,"赵六","121212"));
if(res > 0){
System.out.println("插入成功");
}
//提交事物
sqlSession.commit();
sqlSession.close(); //不变
}
3. 修改 update
UserMapper.java
//update修改用户
int updateUser(User user);
UserMapper.xml
<!--更新用户信息-->
<update id="updateUser" parameterType="com.guo.pojo.User">
update mybatis.user set name =#{name},pwd=#{pwd} where id = #{id};
</update>
UserMapperTest.java
(测试类)
增删改需要提交事物
@Test
public void updateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();//不变
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//不变
mapper.updateUser(new User(4,"更改了","123123"));
//提交事物
sqlSession.commit();
sqlSession.close();//不变
}
4. 删除 delete
UserMapper.java
//delete 删除一个用户
int deleteUser(int id);
UserMapper.xml
<!--删除一个用户-->
<delete id="deleteUser" parameterType="int">
delete from mybatis.user where id = #{id};
</delete>
UserMapperTest.java
(测试类)
增删改需要提交事物
@Test
public void deleteUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();//不变
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//不变
mapper.deleteUser(4);
//必须提交事物
sqlSession.commit();
sqlSession.close();//不变
}
5. 分析错误
-
正确写法:
<mapper namespace="com.guo.dao.UserMapper"> <!--绑定-->
错误写法:
<mapper namespace="com/guo/dao/UserMapper"> <!--绑定-->
-
标签不能匹配错:例如:
insert
对应插入的方法 -
mybatis-config.xml
中:
正确写法:resource
是资源路径,绑定mapper需要使用路径
,使用/
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册!-->
<mappers>
<mapper resource="com/guo/dao/UserMapper.xml"/>
</mappers>
错误写法:
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册!-->
<mappers>
<mapper resource="com.guo.dao.UserMapper.xml"/>
</mappers>
-
程序数据库配置文件,必须符合规范!
-
NullPointerException
空指针异常 没有注册到资源!
需要注意MybatisUtils.java
中这两行的关系,是否能注册到资源!
private static SqlSessionFactory sqlSessionFactory;
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //创建流
-
输出的
target
文件夹中的xml
文件中存在中文乱码问题! -
maven资源没有导出问题!
在pom.xml
中配置:
<!--maven由于它的约定大于配置,我们以后可能遇到我们自己写的配置文件,无法被导出或者生效的问题,解决方法:-->
<!--在build中配置resources,来防止我们资源导出失败的问题!-->
<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>
6. Map
遇到问题:当前类字段是三个,可以写成(id,name,pwd) values (#{id},#{name},#{pwd})
形式。
UserMapper.xml
<!--对象中的属性,可以直接取出来-->
<insert id="addUser" parameterType="com.guo.pojo.User" >
insert into mybatis.user (id,name,pwd) values (#{id},#{name},#{pwd});
</insert>
如果实体类或者数据库表中字段过多,不太建议都写成以上这样,建议使用Map
。
UserMapper.java
//万能的Map 不需要传
int addUser2(Map<String,Object> map);
UserMapper.xml
<!--对象中的属性,map对象不需要一一对应,传递map的key-->
<insert id="addUser2" parameterType="map">
insert into mybatis.user(id,name,pwd) values (#{userid},#{userName },#{passWord});
</insert>
UserMapperTest.java
(测试类)
@Test
public void addUser2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();//不变
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//不变
Map<String,Object> map = new HashMap<String,Object>();
map.put("userid",5);//随意制造参数
map.put("userName","孙七");//
map.put("passWord","12345");
mapper.addUser2(map);
//必须提交事物
sqlSession.commit();
sqlSession.close();//不变
}
6.1 修改查询 (根据id查询用户)
UserMapper.java
//根据ID查询用户
//User getUserById(int id); 原来的
User getUserById2(Map<String,Object> map);//改成
UserMapper.xml
<select id="getUserById2" parameterType="map" resultType="com.guo.pojo.User">
select * from mybatis.user where id = #{helloid} and name = #{name};
</select>
UserMapperTest.java
(测试类)
@Test
public void getUserById2(){
SqlSession sqlSession = MybatisUtils.getSqlSession();//不变
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//不变
Map<String,Object> map = new HashMap<String,Object>();
map.put("helloId",1);//需要与`UserMapper.xml`对应上
map.put("name","张三");
User user = mapper.getUserById2(map);
System.out.println(user);
sqlSession.close();//不变
}
总结:
- Map传递参数,直接在sql中取出key即可!
parameterType="map"
- 对象传递参数,直接在sql中取对象的属性即可!
parameterType="map"
- 只有一个基本参数的情况下,可以直接在sql中取到!
举个例子:
UserMapper.java
中 getUserById
方法只传了一个值
//根据ID查询用户
User getUserById(int id);
UserMapper.xml
中 parameterType="int"
可以不写了,多个参数用Map
,或者注解
<select id="getUserById" resultType="com.guo.pojo.User">
select * from mybatis.user where id = #{id}
</select>
6.2 模糊查询
-
- Java代码执的时候,传递通配符% %
List<User> userList = mapper.getUserLike("%李%");
- Java代码执的时候,传递通配符% %
-
- 在sql拼接中使用通配符!(容易sql注入)
select * from mybatis.user where name like "%" #{value} "%"
- 在sql拼接中使用通配符!(容易sql注入)
UserMapper.java
//模糊查询
List<User> getUserLike(String value);
UserMapper.xml
中 parameterType="int"
可以不写了,多个参数用Map
,或者注解
<select id="getUserLike" resultType="com.guo.pojo.User">
select * from mybatis.user where name like #{value}
</select>
不要写成:
<select id="getUserLike" resultType="com.guo.pojo.User">
select * from mybatis.user where name like "%"#{value}"%"
</select>
能运行,但是容易造成sql语句拼接,产生sql注入
select * from mybatis.user where id = ?
select * from mybatis.user where id = 1 or 1 = 1
UserMapperTest.java
(测试类)
@Test
public void getUserLike(){
SqlSession sqlSession = MybatisUtils.getSqlSession();//不变
UserMapper mapper = sqlSession.getMapper(UserMapper.class);//不变
List<User> userList = mapper.getUserLike("%李%");
for (User user : userList) {
System.out.println(user);
}
sqlSession.close();//不变
}
7. 配置解析
MyBatis配置文档:
Mybatis的配置文件包含了深深影响myBatis行为的设置和属性信息。
7.1 核心配置文件
mybatis-config.xml
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
7.2 环境配置(environments)
学会使用配置多套运行环境,不过要记住:尽管可以配置多个环境,但每个SqlSessionFactory
实例只能选择一种环境
<environments default="test"><!--这里的default对应environment的id-->
<environment id="development">
<transactionManager type="JDBC"> <!--Mybatis默认的事务管理器就是JDBC-->
<property name="..." value="..."/>
</transactionManager>
<dataSource type="POOLED"> <!--数据源是连接数据库:连接池: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"> <!--使用的是test环境-->
<transactionManager type="JDBC">
<property name="..." value="..."/>
</transactionManager>
<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>
7.3 属性properties
我们可以通过properties
属性来实现引用配置文件
这些属性都是课外不配置且可以动态替换的,既可以在典型的java属性文件中配置,亦可以通过properties元素的子元素来传递。【db.properties】
<!--官方文档-->
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
也可以编写一个配置文件db.properties
<!-- db.properties -->
driver = com.mysql.jdbc.Driver
url =jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
username =
password =
在核心配置文件中(mybatis-config.xml)
引入,在xml中,所有的标签都可以规定其顺序
可以直接引入外部文件
可以在起哄增加一些属性配置
如果两个文件有同一个字段,优先使用外部配置文件
<?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>
<!--引入外部配置文件--> <!--如果两个文件有同一个字段,优先使用外部配置文件-->
<properties resource="db.properties">
</properties>
<!--环境 environments下可以配置多个environment环境 环境名称是id="" environments default=使用哪个个环境就写哪个环境的id-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/> <!--事物管理-->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/> <!--驱动--><!--编码--> <!--&就是and serverTimezone时区-->
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册!-->
<mappers>
<mapper resource="com/guo/dao/UserMapper.xml"/>
</mappers>
</configuration>
当然也可以这样配置:
db.properties
driver = com.mysql.jdbc.Driver
url =jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT
<?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>
<!--引入外部配置文件--> <!--如果两个文件有同一个字段,优先使用外部配置文件-->
<properties resource="db.properties">
<property name="username" value=""/>
<property name="pwd" value=""/>
</properties>
<!--环境 environments下可以配置多个environment环境 环境名称是id="" environments default=使用哪个个环境就写哪个环境的id-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/> <!--事物管理-->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/> <!--驱动--><!--编码--> <!--&就是and serverTimezone时区-->
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${pwd}"/>
</dataSource>
</environment>
</environments>
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册!-->
<mappers>
<mapper resource="com/guo/dao/UserMapper.xml"/>
</mappers>
</configuration>
7.4 类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,存在的意义仅在于用来减少类完全限定名的冗余。
第一种,在实体类比较少的时候使用的方式,这种方式可以自定义:
<!--可以给实体类起别名-->
<typeAliases>
<typeAlias alias="User" type="com.guo.pojo.User"/>
</typeAliases>
第二种,如果实体类比较多,建议也可以这样写:
扫描实体类的包,它的默认别名就为这类的类名首字母
<!--可以给实体类起别名-->
<typeAliases>
<package name="com.guo.pojo"/>
</typeAliases>
<select id="getUserList" resultType="user" > <!--这里user最好,也可以用User-->
<!--执行SQL-->
select * from mybatis.user;
</select>
使用第二种方式,还可以在实体类上增加注解
直接起名字
User.java
实体类
import org.apache.ibatis.type.Alias;
@Alias("user")
public class User {
...
}
7.5 设置(setting)
原因;原来很多公司用Oracle数据库,在其数据库中,字段lastName
常常会转化为
LASTNAME
,因此程序员默认开始使用_
来分隔字段。现在加下面的参数last_Name
转化为lastName
配置
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>
7.6 插件及其他
mybatis插件:
插件举例:
- MyBatis Generator Core
- MyBatis Plus
- 通用mapper
7.6.1 映射器(mappers)
MapperRegistry
:注册绑定我们的Mapper文件
方式一:【推荐使用】
mybatis-config.xml
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册!-->
<mappers>
<mapper resource="com/guo/dao/UserMapper.xml"/>
</mappers>
方式二:使用class文件绑定注册
mybatis-config.xml
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册!-->
<mappers>
<mapper class="com.guo.dao.UserMapper"/>
</mappers>
注意点:
- 接口和它的Mapper配置文件必须同名!
- 接口和它的的配置文件必须在同一个包下!
方式三:使用扫描包进行注入绑定
mybatis-config.xml
<!--每一个Mapper.xml都需要在Mybatis核心配置文件中注册!-->
<mappers>
<package name="com.guo.dao"/>
</mappers>
注意点:
- 接口和它的Mapper配置文件必须同名!
- 接口和它的的配置文件必须在同一个包下!
如果配置不对会报错:
8. 生命周期和作用域
生命周期和作用域是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder:
- 一旦创建了 SqlSessionFactory,就不再需要它了
- 作用域 :局部变量
SqlSessionFactory:
- 可以理解为数据库连接池
- SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
- 多次重建 SqlSessionFactory 被视为一种代码“坏习惯”
- 因此 SqlSessionFactory 的最佳作用域是应用作用域。全局变量
- 最简单的就是使用单例模式或者静态单例模式。
SqlSession:
- 连接到数据库连接池的一个请求。
- SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
- 用完之后需要关闭,否则资源被占用!