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
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
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
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
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需要使用路径 ,使用 /
<mappers>
<mapper resource="com/guo/dao/UserMapper.xml"/>
</mappers>
错误写法:
<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 中配置:
<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
int addUser2(Map<String,Object> map);
UserMapper.xml
<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
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);
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 方法只传了一个值
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("%李%"); -
- 在sql拼接中使用通配符!(容易sql注入)
select * from mybatis.user where name like "%" #{value} "%"
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">
<environment id="development">
<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>
<environment id="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
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 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>
</environments>
<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 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="${pwd}"/>
</dataSource>
</environment>
</environments>
<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" >
select * from mybatis.user;
</select>
使用第二种方式,还可以在实体类上增加注解 直接起名字 User.java 实体类
import org.apache.ibatis.type.Alias;
@Alias("user")
public class User {
...
}
7.5 设置(setting)
mybatis官方文档(设置):
原因;原来很多公司用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
<mappers>
<mapper resource="com/guo/dao/UserMapper.xml"/>
</mappers>
方式二:使用class文件绑定注册 mybatis-config.xml
<mappers>
<mapper class="com.guo.dao.UserMapper"/>
</mappers>
注意点:
- 接口和它的Mapper配置文件必须同名!
- 接口和它的的配置文件必须在同一个包下!
方式三:使用扫描包进行注入绑定 mybatis-config.xml
<mappers>
<package name="com.guo.dao"/>
</mappers>
注意点:
- 接口和它的Mapper配置文件必须同名!
- 接口和它的的配置文件必须在同一个包下!
如果配置不对会报错:
8. 生命周期和作用域
生命周期和作用域是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder:
- 一旦创建了 SqlSessionFactory,就不再需要它了
- 作用域 :局部变量
SqlSessionFactory:
- 可以理解为数据库连接池
- SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
- 多次重建 SqlSessionFactory 被视为一种代码“坏习惯”
- 因此 SqlSessionFactory 的最佳作用域是应用作用域。全局变量
- 最简单的就是使用单例模式或者静态单例模式。
SqlSession:
- 连接到数据库连接池的一个请求。
- SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
- 用完之后需要关闭,否则资源被占用!
|