Java后台应用项目开发 Part 3 - MyBatis 框架的使用

文章导航

«返回课程汇总页面

Java后台应用项目开发 Part 3 - MyBatis 框架的使用

【版本】

当前版本号v20211012

版本修改说明
v20211012修正 spring-mvc.xml 注释
v20211009修正 SqlMapConfig.xml 内容,缺失了一个",新增resource目录相关说明
v20210927初始化版本

【实验名称】 实验3.1 新建 MyBatis 项目

【实验目的】

【实验环境】

【实验资源】

【实验步骤】

  1. 参考实验2.2,新建一个新的 Maven Web 开发项目MyBatis

  2. 在 POM.xml 文件中加入依赖包的配置。

<dependencies>
        <!-- JUnit 框架 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>
        <!-- MySQL 连接驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.38</version>
        </dependency>
        <!-- MyBatis 包 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.4</version>
        </dependency>
    </dependencies>
  1. 在项目下新建目录src\main\resources\db\migration,用于存放数据库 SQL 脚本文件。

注意这里 IDEA 显示的db.migration,并不是目录名称为db.migration,而是一个层级目录如下所示。

resources
  |- db
    |- migration
  1. 新建2个 SQL 脚本文件。
create database mobile_shop;
create user 'mshop'@'localhost' identified by 'hudp3ymVq5pMU47h';
create user 'mshop'@'%' identified by 'hudp3ymVq5pMU47h';
grant all on mobile_shop.* to 'mshop'@'localhost';
grant all on mobile_shop.* to 'mshop'@'%';
CREATE TABLE `ms_user` (
	`user_id` INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY comment '用户ID',
	`username` VARCHAR(50) NOT NULL comment '用户名',
	`password` VARCHAR(50) NOT NULL comment '密码'
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;

insert into `ms_user` (`username`,`password`) values('zhangsan','123456');
  1. 启动MySQL,使用 HeidiSQL 连接 MySQL,并依照序号,先后执行以上2个 SQL 脚本文件。正常执行以后,运行以下 SQL 脚本应该能够查询到一条记录。
use mobile_shop;
select * from ms_user;
  1. 编写以下配置文件。请注意存放的目录路径,没有该目录可以自己创建。
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mobile_shop?useUnicode=true&characterEncoding=UTF-8
user=mshop
pwd=hudp3ymVq5pMU47h
<?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>
	<!-- 引用db.properties配置文件 -->
	<properties resource="db.properties"/>
	<environments default="environment">
		<environment id="environment">
			<!-- JDBC类型:有提交和回滚的设置 -->
			<transactionManager type="JDBC" />
			<!-- POOLED类型:数据库连接池 -->
			<!-- 配置数据库连接信息 -->
			<dataSource type="POOLED">
				<!-- value的值引用db.properties中的值 -->
				<property name="driver" value="${driver}" />
				<property name="url" value="${url}"/>
				<property name="username" value="${user}" />
				<property name="password" value="${pwd}" />
			</dataSource>
		</environment>
	</environments>
	<!-- 配置映射文件 -->
	<mappers>
		<mapper resource="mobileshop/mapper/UserDaoMapper.xml"/>
	</mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"      
 "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="mobileshop.dao.UserDao">
	<select id="findAll" resultType="mobileshop.entity.UserEntity">
		select * from ms_user
	</select>
</mapper>

注意这里 IDEA 显示的mobileshop.mapper,并不是目录名称为mobileshop.mapper,而是一个层级目录如下所示。

resources
  |- mobileshop
    |- mapper
  1. 编写以下3个类。请注意存放的目录路径,没有该目录可以自己创建。
package mobileshop.dao;

import mobileshop.entity.UserEntity;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserDao {
    List<UserEntity> findAll();
}
package mobileshop.entity;

public class UserEntity {
    private Long userId;
    private String username;
    private String password;
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public Long getUserId() {
        return userId;
    }
    public void setUserId(Long userId) {
        this.userId = userId;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
}
package mobileshop.utils;
import java.io.InputStream;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class MybatisUtils {
	//获取SqlSession的方法
	public static SqlSession getSqlSession(){
		//SqlSessionFactoryBuilder ——> SqlSessionFactory ——> SqlSession
		SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
		//加载sqlMapConfig.xml
		ClassLoader loader= MybatisUtils.class.getClassLoader();//MybatisUtil:自己写的类都可以
		InputStream inStream=loader.getResourceAsStream("SqlMapConfig.xml");
		SqlSessionFactory factory=builder.build(inStream);
		SqlSession session=factory.openSession();
		return session;
	}
}
  1. 编写单元测试用例,运行testFindAll方法,测试能否正常调用UserDaofindAll方法。正常情况下测试用例会通过。
package mobileshop.dao;

import mobileshop.entity.UserEntity;
import mobileshop.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class UserDaoTest {

    private SqlSession session;
    private UserDao userDao;

    @Before
    public void beforeTest(){
        session=MybatisUtils.getSqlSession();
        userDao=session.getMapper(UserDao.class); //生成的一个动态代理
    }

    @Test
    public void testFindAll(){
        List<UserEntity> list= userDao.findAll();
        assertTrue(list.size()>0);
    }

    @After
    public void closeSession(){
        if(session!=null) {
            session.commit();//提交更改
            session.close();
        }
    }
}

【实验名称】 实验3.2 开发用户的增删查改功能

【实验目的】

【实验环境】

【实验资源】

【实验要求】

  1. UserDao类新增以下方法。
package mobileshop.dao;

import mobileshop.entity.UserEntity;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserDao {
    /**
     * 查找所有用户
     * @return
     */
    List<UserEntity> findAll();

    /**
     * 按用户名查找用户
     * @return
     */
    UserEntity findByUserName(String username);

    /**
     * 按用户名更新用户密码
     * @return
     */
    int updatePassword(@Param("username")String username,@Param("password")String password);

    /**
     * 新增用户
     * @param ue
     * @return
     */
    int save(UserEntity ue);

    /**
     * 根据传入的用户名删除用户
     * @param username
     * @return
     */
    int deleteByUsername(String username);
}

  1. 测试用例修改如下,该测试用例会测试UserDao新增的所有方法。
package mobileshop.dao;

import mobileshop.entity.UserEntity;
import mobileshop.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class UserDaoTest {

    private SqlSession session;
    private UserDao userDao;

    @Before
    public void beforeTest(){
        session=MybatisUtils.getSqlSession();
        userDao=session.getMapper(UserDao.class); //生成的一个动态代理
    }

    @Test
    public void testFindAll(){
        List<UserEntity> list= userDao.findAll();
        assertTrue(list.size()>0);
    }

    @Test
    /**
     * 另一种方法运行findAll
     */
    public void testFindAll2(){
        List<UserEntity> list= session.selectList("findAll");
        assertTrue(list.size()>0);
    }

    @Test
    /**
     * 测试 findByUserName 功能
     */
    public void testFindByUserName(){
        String username="zhangsan";
        UserEntity ue=userDao.findByUserName(username);
        assertEquals(username,ue.getUsername());
    }

    @Test
    /**
     * 另一种方法调用 findByUserName 功能
     */
    public void testFindByUserName2(){
        String username="zhangsan";
        UserEntity ue=session.selectOne("findByUserName",username);
        assertEquals(username,ue.getUsername());
    }

    @Test
    /**
     * 测试 updatePassword 功能
     */
    public void testUpdatePassword(){
        int rs=userDao.updatePassword("zhangsan","123456");
        assertEquals(1,rs);
    }

    @Test
    /**
     * 另一种方法调用 updatePassword 功能
     */
    public void testUpdatePassword2(){
        Map<String,String> map=new HashMap<>();
        map.put("username","zhangsan");
        map.put("password","123456");
        int rs=session.update("updatePassword",map);
        assertEquals(1,rs);
    }

    @Test
    /**
     * 测试 save 功能
     */
    public void testSave(){
        UserEntity u=new UserEntity();
        u.setUsername("lisi");
        u.setPassword("135790");
        int rs=userDao.save(u);
        assertEquals(1,rs);
    }

    @Test
    /**
     * 另一种方法调用 save 功能
     */
    public void testSave2(){
        UserEntity u=new UserEntity();
        u.setUsername("lisi");
        u.setPassword("135790");
        int rs=session.insert("save",u);
        assertEquals(1,rs);
    }

    @Test
    /**
     * 测试 deleteByUsername 功能
     */
    public void testDeleteByUsername(){
        UserEntity u=new UserEntity();
        u.setUsername("wangwu");
        u.setPassword("135790");
        userDao.save(u);
        int rs=userDao.deleteByUsername("wangwu");
        assertEquals(1,rs);
    }

    @Test
    /**
     * 另一种方法调用 deleteByUsername 功能
     */
    public void testDeleteByUsername2(){
        UserEntity u=new UserEntity();
        u.setUsername("wangwu");
        u.setPassword("135790");
        userDao.save(u);
        int rs=session.delete("deleteByUsername","wangwu");
        assertEquals(1,rs);
    }

    @After
    public void closeSession(){
        if(session!=null) {
            session.commit();//提交更改
            session.close();
        }
    }
}

  1. 请你根据UserDao新增的方法,完善UserDaoMapper.xml,并且能够让UserDaoTest所有测试通过。

【实验名称】 实验3.3 集成 MyBatis 框架到 Web 项目

【实验目的】

【实验环境】

【实验资源】

【实验要求】

  1. 结合实验2.2和实验3.2,完善真实访问数据库的登录功能。

  2. 新建 Maven 项目,项目目录结构如下:

  3. 以下为代码提示:

package mobileshop.controller;

import mobileshop.entity.UserEntity;
import mobileshop.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class LoginController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/login")
    public String login(){
        return "login";
    }

    @RequestMapping(value = "/signin")
    public String signIn(String username, String password){
        //请完善代码
    }
}
package mobileshop.dao;

import mobileshop.entity.UserEntity;

public interface UserDao {
    UserEntity findByUserName(String username);
}
package mobileshop.entity;

public class UserEntity {
    private Long userId;
    private String username;
    private String password;
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

}
package mobileshop.service;


import mobileshop.entity.UserEntity;

public interface UserService {
    boolean validUserPwd(UserEntity ue);

    UserEntity getUserByUsername(String username);
}
package mobileshop.service;

import mobileshop.dao.UserDao;
import mobileshop.entity.UserEntity;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService{

    @Autowired
    private UserDao userDao;

    @Override
    public boolean validUserPwd(UserEntity ue) {
        //请完善代码。
    }

    @Override
    public UserEntity getUserByUsername(String username) {
        return userDao.findByUserName(username);
    }
}
<?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="mobileshop.dao.UserDao">
	<select id="findByUserName" parameterType="string"
			resultType="mobileshop.entity.UserEntity">
		select * from ms_user where username=#{username}
	</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd">
    <!--配置注解扫描-->
    <context:component-scan base-package="mobileshop.controller,mobileshop.service"/>
    <!-- SpringMVC注解支持 -->
    <mvc:annotation-driven/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/html/" />
        <property name="suffix" value=".html" />
    </bean>

    <util:properties id="jdbc" location="classpath:db.properties"/>

    <bean id="dbcp" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="#{jdbc.driver}"/>
        <property name="url" value="#{jdbc.url}"/>
        <property name="username" value="#{jdbc.user}"/>
        <property name="password" value="#{jdbc.pwd}"/>
    </bean>

    <!-- 配置SqlSessionFactoryBean -->
    <!-- 可以定义一些属性来指定Mybatis框架的配置信息 -->
    <bean id="ssf" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据源,注入连接信息 -->
        <property name="dataSource" ref="dbcp"/>
        <!-- 用于指定sql定义文件的位置(加classpath从src下找) -->
        <property name="mapperLocations"
                  value="classpath:mobileshop/mapper/*.xml"/>
    </bean>

    <!-- 配置MapperScannerConfigurer -->
    <!-- 按指定包扫描接口,批量生成接口实现对象,id为接口名首字母小写 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定扫描 mobileshop.dao 包下所有接口 -->
        <property name="basePackage"
                  value="mobileshop.dao"/>
        <!-- 注入sqlSessionFactory(此句可不写,自动注入sqlSessionFactory) -->
        <property name="sqlSessionFactory" ref="ssf"/>
    </bean>
</beans>