1 回顾自定义的MyBatis、流程再分析
2 MyBatis的CRUD(基于代理dao的方式)
2.1 回顾MyBatis的环境搭建-实现一个查询所有的功能
我们来新建一个Module命名为day02_01mybatisCRUD。我们可以把昨天的Module里的log4j的配置文件直接拷贝道我们新建的Module里。因为我们不需要是新的jar所以我们可以按照昨天的pom.xml来修改我们新建的Module的pom.xml。
<?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>com.itheima</groupId>
<artifactId>day02_01mybatis_CRUD</artifactId>
<version>1.0-SNAPSHOT</version>
<!--打包方式-->
<packaging>jar</packaging>
<!--依赖包-->
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
然后我们创建一个实体类User.java
public class User implements Serializable {
private Integer id;
private String username;
private String address;
private String sex;
private Date birthday;
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 getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", address='" + address + '\'' +
", sex='" + sex + '\'' +
", birthday=" + birthday +
'}';
}
}
下面来创建MyBatis的主配置文件SqlMapperConfig.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">
<!--上面是mybatis的主配置文件的约束-->
<configuration>
<!--配置环境-->
<environments default="mysql">
<!--配置mysql的环境-->
<environment id="mysql">
<!--配置事务-->
<transactionManager type="JDBC"></transactionManager>
<!--配置连接池-->
<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="123456"/>
</dataSource>
</environment>
</environments>
<!--配置映射文件的位置-->
<mappers>
<mapper resource="com/itheima/dao/IUserDao.xml"></mapper>
</mappers>
</configuration>
然后我们在创建Dao接口,IUserDao.java
/**
* 用户的持久层接口
*/
public interface IUserDao {
/**
* 查询所有用户的操作
*/
List<User> findAll();
}
然后再根据MyBatis的主配置文件中的 mapper 来创建IUserDao的M映射配置文件IUserDao.xml。这里我们在resources里创建包的时候,要想一次把这个包的路径全部创建出来,需要填入 com/itheima/dao 这里也创建包,然后在这个包中创建IUserDao.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表示Dao的接口-->
<mapper namespace="com.itheima.dao.IUserDao">
<!--配置查询所有 resultType 表示传递的参数类型-->
<select id="findAll" resultType="com.itheima.domain.User">
select * from user;
</select>
</mapper>
下面来创建一个测试类 MybatisTest.java 测试我们写的代码。
/**
* 测试MyBatis的CRUD操作
*/
public class MybatisTest {
/**
* 查询所有的测试
*/
@Test
public void testFindAll() throws Exception{
//1.读取配置文件,生成字节输入流
InputStream in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2.获取SqlSessionFactor对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(in);
//3.获取SqlSession对象
SqlSession session = sessionFactory.openSession();
//4.获取Dao的代理对象
IUserDao dao = session.getMapper(IUserDao.class);
//5.查询所有方法
List<User> users = dao.findAll();
for (User user : users) {
System.out.println(user);
}
}
}
我们执行以下测试类中的测试方法控制台输出如下,可以看出程序正常执行啦。
2.2 MyBatis的CRUD和MyBatis中的参数(参数的各种类型)深入及结果(结果集的封装)的深入
我们在上面创建的Module的基础上来实心MyBatis的CRUD操作和对参数的设置和结果集的封装进行配置。首先修改IUserService.java
/**
* 用户的持久层接口
*/
public interface IUserDao {
/**
* 查询所有用户的操作
*/
List<User> findAll();
/**
* 保存用户
*/
void saveUser(User user);
/**
* 更新用户
*/
void updateUser(User user);
/**
* 根据id删除用户
*/
void deleteUser(Integer userId);
/**
* 根据id查询用户
*/
User findById(Integer userId);
/**
* 根据名称模糊查询用户信息
*/
List<User> findByName(String username);
/**
* 查询总的用户数
*/
int findTotal();
/**
* 根据QueryVo中的条件查询用户
*/
List<User> findUserByVo(QueryVo vo);
}
创建一个查询条件类 QueryVo.java
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
然后就是修改我们的MyBatis的映射配置文件IUserDao.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表示Dao的接口-->
<mapper namespace="com.itheima.dao.IUserDao">
<!--配置查询结果的列名和实体类的属性名的对应关系 property是实体类中的属性名,column是数据库中的列名-->
<resultMap id="userMap" type="com.itheima.domain.User">
<!--主键字段的对应 property 表示实体类中的属性名字,column表示数据库表的列名-->
<id property="id" column="id"></id>
<!--非主键字段的对应-->
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
</resultMap>
<!--配置查询所有,id表示方法名, resultType表示返回的结果集封装到哪里-->
<!--当实体类中的属性名和数据库中的列名不一致时,可以在sql语句中起别名,也可以使用resultMap进行映射-->
<!--<select id="findAll" resultType="com.itheima.domain.User">-->
<select id="findAll" resultMap="userMap">
<!--select id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user-->
select * from user;
</select>
<!--保存用户 parameterType表示方法的参数类型-->
<insert id="saveUser" parameterType="com.itheima.domain.User">
<!--配置插入操作后,获取插入数据的id
keyProperty id的属性名称对应实体类里的属性名,
keyColumn id的列名对应表
order 表示在insert前执行还是插入后执行
-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
select last_insert_id();
</selectKey>
insert into user(username,address,sex,birthday) values(#{username},#{address},#{sex},#{birthday});
</insert>
<!--更新用户-->
<update id="updateUser" parameterType="com.itheima.domain.User">
update user set username =#{username}, address =#{address}, sex=#{sex},birthday =#{birthday} where id=#{id};
</update>
<!--删除用户 当方法只有一个参数时,并且是基本类型或基本类的包装类时,{uid}就是一个占位符,写什么都行-->
<delete id="deleteUser" parameterType="Integer">
delete from user where id=#{uid};
</delete>
<!--根据id查询一个用户-->
<select id="findById" parameterType="Integer" resultType="com.itheima.domain.User">
select * from user where id=#{uid};
</select>
<!-- 根据名称模糊查询 -->
<select id="findByName" parameterType="String" resultType="com.itheima.domain.User">
<!--这种方式,要在调用方法的时候加%
这
在实际执行的时候是 select * from user where username like ?;使用了占位符
使用的是 PrepatedStatement的参数占位符,建议使用这个
-->
select * from user where username like #{uname};
<!--下面这种方式,在调用方法的时候不用加%,但是这个站位符必须写出value,因为这个在源码中写死了
这种方法不常用,在实际执行的时候是 select * from user where username like '%小%'; 拼接的字符串
这个是用 Statement对象的字符串拼接的SQL,不建议使用,易SQL注入
-->
<!--select * from user where username like '%${value}%';-->
</select>
<!--获取用户的总计数条数-->
<select id="findTotal" resultType="int">
select count(*) from user;
</select>
<!--根据QueryVo的条件查询用户-->
<select id="findUserByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User">
select * from user where username like #{user.username}; <!--QueryVo对象中有一个属性为 user-->
</select>
</mapper>
在这个配置文件中我们展示了MyBatis的CRUD操作的映射配置和参数的传递配置和结果集的封装处理。
下面在来修改一下测试类MybatisTest.java
/**
* 测试MyBatis的CRUD操作
*/
public class MybatisTest {
private InputStream in = null;
private SqlSession session = null;
private IUserDao dao = null;
/**
* 初始化Mybatis
*/
@Before //用于在测试方法之前执行
public void init() throws Exception {
//1.读取配置文件,生成字节输入流
in = Resources.getResourceAsStream("SqlMapperConfig.xml");
//2.获取SqlSessionFactor对象
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory sessionFactory = builder.build(in);
//3.获取SqlSession对象
session = sessionFactory.openSession();
//4.获取Dao的代理对象
dao = session.getMapper(IUserDao.class);
}
/**
* 释放资源
*
* @throws Exception
*/
@After //用于在测试方法之后执行
public void destroy() throws Exception {
//提交事务
session.commit();
//和上面一句一样
// session.commit(true);
if (in != null)
in.close();
if (session != null)
session.close();
}
/**
* 查询所有的测试
*/
@Test
public void testFindAll() {
//5.查询所有方法
List<User> users = dao.findAll();
for (User user : users) {
System.out.println(user);
}
}
/**
* 保存用户测试
*/
@Test
public void testSaveUser() {
User user = new User();
user.setUsername("mybatis last insertUser");
user.setAddress("天津");
user.setSex("女");
user.setBirthday(new Date());
System.out.println("保存操作之前:" + user);
//5.执行保存方法
dao.saveUser(user);
System.out.println("保存操作之后:" + user);
}
/**
* 更新用户测试
*/
@Test
public void testUpdateUser() {
User user = new User();
user.setId(5);
user.setUsername("mybatis update user");
user.setAddress("上海");
user.setSex("女");
user.setBirthday(new Date());
//5.执行更新用户方法
dao.updateUser(user);
}
/**
* 删除用户测试
*/
@Test
public void testDeleteUser() {
//5.执行删除用户方法
dao.deleteUser(5);
}
/**
* 根据id查询用户测试
*/
@Test
public void testFindById() {
//5.执行根据id查询用户有方法
User user = dao.findById(2);
System.out.println(user);
}
/**
* 根据username模糊查询
*/
@Test
public void testFindByName() {
// 执行根据username模糊查询方法
// List<User> users = dao.findByName("%小%");
List<User> users = dao.findByName("小");
for (User user : users) {
System.out.println(user);
}
}
/**
* 查询用户的总数
*/
@Test
public void testFindTotal() {
//执行查询用户的总数方法
int total = dao.findTotal();
System.out.println("总人数:" + total);
}
/**
* 测试使用QueryVo作为查询条件的模糊查询
*/
@Test
public void testFindByVo() {
//执行根据username模糊查询方法
QueryVo queryVo = new QueryVo();
User user = new User();
user.setUsername("%小%");
queryVo.setUser(user);
List<User> users = dao.findUserByVo(queryVo);
for (User u : users) {
System.out.println(u);
}
}
}
整个Module的结构如下