6.1 项目环境
6.1.1 SQL数据
-- 创建数据库
create database mybatis
-- 创建user表
create table user (
id int primary key auto_increment,
username varchar(20) not null,
birthday date,
sex char(1) default '男',
address varchar(50)
);
insert into user values (null, '侯大利','1980-10-24','男','江州');
insert into user values (null, '田甜','1992-11-12','女','阳州');
insert into user values (null, '王永强','1983-05-20','男','阳州');
insert into user values (null, '杨红','1995-03-22','女','秦阳');
6.1.2 项目目录
6.1.3 添加依赖
<?xml version="1.0" encoding="UTF-8"?>
<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.0</modelVersion>
<groupId>cn.guardwhy</groupId>
<artifactId>03_Mybatis_CRUD</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!--倒入项目所需依赖-->
<dependencies>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.0</version>
</dependency>
<!--mysql连接依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<!--日志依赖-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!--测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</dependency>
</dependencies>
</project>
6.1.4 sqlMapConfig.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>
<environments default="default">
<!--环境变量-->
<environment id="default">
<!--事务管理器:由JDBC管理事务 -->
<transactionManager type="JDBC"/>
<!--数据源配置信息:POOLED 使用连接池 -->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 加载其他的映射文件 -->
<mappers>
<mapper resource="cn/guardwhy/dao/UserMapper.xml"/>
</mappers>
</configuration>
6.1.5 log4j.properties
### 设置Logger输出级别和输出目的地 ###
log4j.rootLogger=debug, stdout
### 把日志信息输出到控制台 ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout
6.1.5 User实体类
package cn.guardwhy.domain;
import java.sql.Date;
/**
* 用户实体类
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
}
6.2 通过id查询用户
6.2.1 UserMapper接口
- 添加User findUserById(Integer id)方法
- 参数使用引用类型
package cn.guardwhy.dao;
import cn.guardwhy.domain.User;
/**
* 用户dao的接口
*/
public interface UserMapper {
/**
* 通过id查询一个用户
*/
User findUserById(Integer id);
}
6.2.2 UserMapper.xml
- 添加select查询标签,并且设置属性id、parameterType、resultType
- 编写查询语句,使用占位符#{变量名}
- 在resources资源下创建cn/guardwhy/dao目录
<?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 指定接口的类全名-->
<mapper namespace="cn.guardwhy.dao.UserMapper">
<!--
查询语句id: 接口中方法的名字 resultType:返回的实体类的类型,类全名
-->
<select id="findUserById" resultType="cn.guardwhy.domain.User" parameterType="java.lang.Integer">
select * from user where id = #{id}
</select>
</mapper>
6.2.3 测试类
- 声明静态成员变量:SqlSessionFactory
- 成员变量:SqlSession
- 成员变量:UserMapper
- 在@BeforeClass中创建工厂对象
- 在@Before中创建会话对象和userMapper对象
- 在@Test中编写通过id查询用户的方法
package cn.guardwhy.test;
import cn.guardwhy.dao.UserMapper;
import cn.guardwhy.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.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.io.InputStream;
/**
* 测试类
*/
public class TestUserDao {
// 会话工厂
private static SqlSessionFactory factory;
// 会话
private SqlSession session;
// 接口
private UserMapper userMapper;
/**
* 类加载的时候执行一次,创建会话工厂
*/
@BeforeClass
public static void init() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(inputStream);
}
/**
* 每个测试方法前都会执行的方法
*/
@Before
public void begin(){
session = factory.openSession(true); //true设置为自动提交
// 创建代理对象
userMapper = session.getMapper(UserMapper.class);
}
@Test
public void testFindUserById(){
User user = userMapper.findUserById(1);
System.out.println(user);
}
}
6.3 模糊查询用户
6.3.1 typeAliases(别名)
作用:给用户自定义的实体类定义别名
1) 单个别名typeAlias
<!--定义实体类单个别名-->
<!--
typeAlias:
1.type:指定实体类全名
2.alias: 指定别名,如果省略这个属性,默认使用类名字做为别名,别名不区分大小写,通常别名使用小写。
-->
<typeAlias type="cn.guardwhy.domain.User"/>
2) 包扫描配置别名
<!--定义实体类别名-->
<typeAliases>
<!--
package指定包名
1. 自动将这个包下所有的实体类定义别名,别名就是类的名字。(在日志输出中会有乱码,不用理会,不影响使用,这是mybatis的bug)
2. 如果有多个子包,只需要指定父包即可。
3. 可以使用多个package标签,指定不同的包名
-->
<package name="cn.guardwhy.domain"/>
</typeAliases>
6.3.2 mappers(映射器)
1) 加载单个映射文件mapper
注:如果是多级目录,是/而不是点号
<!--
指定外面的实体类映射文件
resource: 加载类路径下映射文件,不是点号,是/
url: 可以绝对路径的方式访问映射文件.
class: 导入接口类名,用于注解配置的方式 "cn.guardwhy.dao.UserMapper"
-->
<mapper resource="cn/guardwhy/dao/UserMapper.xml"/>
2) 包扫描加载映射
包扫描方式加载mapper映射文件:
- 要求mapper映射文件,与mapper接口要放在同一个目录
- 要求mapper映射文件的名称,与mapper接口的名称要一致
<!--
package表示扫描这个包下所有的映射文件
1. 接口与映射文件在要同一个目录下
2. 接口的名字与映射文件名字要相同
-->
<package name="cn.guardwhy.dao"/>
6.3.3 mapper接口方法
// 2.通过用户名查询用户
List<User> findUsersByName(String username);
6.3.4 配置mapper映射文件
- 使用字符串拼接符${value}拼接参数
- 字符串的参数类型此处只能使用value名字
- 模糊查询前后使用%,外面使用单引号
<!--
通过名字模糊查询
${value}: 字符串拼接,使用$. 如果是简单类型:(8种基本类型+String类型),这里变量名只能是value
-->
<select id="findUsersByName" parameterType="String" resultType="user">
select * from user where username like '%${value}%'
</select>
6.3.5 sqlMapConfig.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">
<property name="jdbc.username" value="root"/>
<property name="jdbc.password" value="root"/>
</properties>
<!--定义实体类别名-->
<typeAliases>
<!-- package扫描 -->
<package name="cn.guardwhy.domain"/>
</typeAliases>
<environments default="default">
<!-- 其中的一个运行环境,通过id来进行标识-->
<environment id="default">
<!--
事务管理器type的取值:
1. JDBC:由JDBC进行事务的管理
2. MANAGED:事务由容器来管理,后期学习Spring框架的时候,所有的事务由容器管理
-->
<transactionManager type="JDBC"/>
<!--
数据源:
1. POOLED:使用mybatis创建的连接池
2. UNPOOLED:不使用连接池,每次自己创建连接
3. JNDI:由服务器提供连接池的资源,我们通过JNDI指定的名字去访问服务器中资源。
-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--映射器-->
<mappers>
<!-- package表示扫描这个包下所有的映射文件 -->
<package name="cn.guardwhy.dao"/>
</mappers>
</configuration>
6.3.6 测试代码
package cn.guardwhy.test;
import cn.guardwhy.dao.UserMapper;
import cn.guardwhy.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.BeforeClass;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
/**
* 测试类
*/
public class TestUserDao {
// 会话工厂
private static SqlSessionFactory factory;
// 会话
private SqlSession session;
// 接口
private UserMapper userMapper;
/**
* 类加载的时候执行一次,创建会话工厂
*/
@BeforeClass
public static void init() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
factory = builder.build(inputStream);
}
/**
* 每个测试方法前都会执行的方法
*/
@Before
public void begin(){
session = factory.openSession();
// 创建代理对象
userMapper = session.getMapper(UserMapper.class);
}
//通过id查询1个用户
@Test
public void testFindUserById(){
User user = userMapper.findUserById(1);
System.out.println(user);
}
// 通过名字模糊查询
@Test
public void testFindUserByName(){
List<User> users = userMapper.findUsersByName("大");
users.forEach(System.out::println);
}
// 用完后关闭会话
@After
public void end(){
session.close();
}
}
6.4 新增用户
6.4.1 mapper接口方法
// 3.新增用户
int addUser(User user);
6.4.2 配置mapper映射文件
- 新增用户使用insert标签
- 放置新增sql语句,参数类型使用User
- 占位符使用user对象的各个#{属性名}
<!--
添加用户
因为增删改没有查询的结果集,所以不用配置resultType。有返回值,返回影响的行数。
-->
<insert id="addUser" parameterType="user">
insert into user values (null, #{username},#{birthday},#{sex},#{address})
</insert>
6.4.3 测试代码
插入新的记录:
/**
添加1个用户
在mybatis中增删改,默认是手动提交事务
1. 设置成自动提交 factory.openSession(true);
2. 自己手动提交 session.commit();
*/
@Test
public void testAddUser(){
User user = new User(null, "老江", Date.valueOf("1975-03-10"),"男","江州");
int row = userMapper.addUser(user);
System.out.println("添加了" + row + "行");
}
// 用完后关闭会话
@After
public void end(){
session.commit(); // 自己手动提交
session.close();
}
6.4.4 提交事务
**事务的处理:**如果Java程序代码执行成功,但是数据库中并没有新增记录。原因是没有提交事务,在对数据库的更新操作中(增、删、改)要求提交事务。
- 自动提交事务
factory.openSession(true)
- 手动提交事务
session.commit()
6.4.5 查询新增记录的主键值
1) 子元素<selectKey>
扫描二维码关注公众号,回复:
12662185 查看本文章
属性 | 说明 |
---|---|
keyColumn | 主键在表中对应的列名 |
keyProperty | 主键在实体类中对应的属性名 |
resultType | 主键的数据类型 |
order | BEFORE: 在添加语句前执行查询主键的语句 AFTER: 在添加语句后执行查询主键的语句 |
2) 映射文件
mysql中的函数:last_insert_id() 得到最后添加的主键
<!--
添加用户
因为增删改没有查询的结果集,所以不用配置resultType。有返回值,返回影响的行数。
-->
<insert id="addUser" parameterType="user">
insert into user values (null, #{username},#{birthday},#{sex},#{address})
<!--
keyColumn:主键在表中对应的列名
keyProperty:主键在实体类中对应的属性名
resultType:主键的数据类型
order:
BEFORE: 在添加语句前执行查询主键的语句,AFTER: 在添加语句后执行查询主键的语句.
-->
<selectKey keyColumn="id" keyProperty="id" resultType="int" order="AFTER">
select last_insert_id()
</selectKey>
</insert>
6.4.6 增加属性
属性 | 说明 |
---|---|
useGeneratedKeys | true 使得自动生成的主键 |
keyColumn | 表中主键的列名 |
keyProperty | 实体类中主键的属性名 |
6.4.7 配置mapper映射文件
<insert id="addUser" parameterType="user" useGeneratedKeys="true"
keyColumn="id" keyProperty="id">
insert into user values (null,#{username},#{birthday},#{sex},#{address})
</insert>
- 说明:直接在insert标签中增加属性的方式,只适合于支持自动增长主键类型的数据库,比如MySQL或SQL Server。
6.4.8 测试代码
/**
通过getId()得到新增的主键值
*/
@Test
public void testAddUser(){
// 得到主键的值
Integer id = user.getId();
System.out.println("生成主键的值:" + id);
}
6.5 修改和删除用户
6.5.1 根据用户id修改用户
6.5.1.1 mapper接口方法
// 4.根据用户Id修改用户
int updateUser(User user);
6.5.1.2 配置mapper映射文件
- 根据用户id修改用户其它属性
- 使用update标签:放置修改sql语句
- 占位符使用:#{属性名}
<!--修改用户-->
<update id="updateUser" parameterType="user">
update user set username=#{username}, birthday=#{birthday},
sex=#{sex}, address=#{address} where id = #{id}
</update>
6.5.1.3 测试代码
- 修改8号用户的名字,生日,性别,地址
- 更新用户对象
@Test
// 更新8号用户
public void testUpdateUser(){
User user = new User(8, "田跃进", Date.valueOf("1976-05-10"), "男", "秦阳");
int row = userMapper.updateUser(user);
System.out.println("更新了" + row + "行");
}
6.5.2 根据用户id删除用户
6.5.2.1 mapper接口方法
// 5.根据用户id删除用户
int deleteUser(Integer id);
6.5.2.2 配置mapper映射文件
- 根据用户Id删除用户
- delete标签:放置删除sql语句
<!--删除用户-->
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
6.5.2.3 测试代码
// 删除用户
@Test
public void testDeleteUser(){
int row = userMapper.deleteUser(12);
System.out.println("删除了" + row + "行记录");
}