在接口中写一个更新数据的代码:
@Mapper public interface UserMapper { int UpdateUser(@Param("ID") int userID,@Param("name") String username); }
<update id="Update"> update user set username=#{name} where userID=#{ID} </update>
1)注意mapper目录是创建在resource文件夹下面的而不是static目录
2)还要注意,你注入一个接口,还是使用@Autowried,然后@Mapper是修饰一个接口的,而不是注入接口
3)我们进行使用select标签的时候,一定要设置resultType和resultMap属性,二者必取其一
@Autowired是来自于Spring,@Mapper是来自于MyBatis,所以说有可能出现不兼容的问题,解决方法就是使用JDK提供的@Resource来进行注入@Mapper;
程序中的小鸟:实现快速跳转,快速切换接口方法和XML,MyBatisX;
对于向数据库中增加数据来说,程序应该返回两种类型的数据,一种是受影响的行数,一种是我想要拿到添加成功的主键,一种是我添加数据后所影响的行数;
编写代码:以向数据库中添加数据为例,根据在浏览器上面输入的username和password进行向数据库中插入数据,可能接口方法声明传过去的直接就是一个对象,但是XML里面的名字必须和对象里面的属性的字段名是一样的;
@Setter
@Getter
@ToString
public class User {
private int ClassID;
private int userID;
private String username;
private String password;
}
第一种:我们想要拿到插入数据后的影响行数,我们还要注意我们在insert标签里面是不用进行设置resultMap和resultType这样的类型的,啥东西也不用设置
1)这是UserController里面的代码:在里面要进行参数校验
@Controller public class UserController { @Autowired UserService userService; @RequestMapping("/InsertAll") @ResponseBody public int InsertAll(User user) { //我们需要在UserController进行参数校验 if(user==null||user.equals("")) { return -1; } return userService.InsertAll(user); } }
2)这是UserService里面的代码:
@Service public class UserService { @Autowired private SpringBootMapper mapper; public int InsertAll(User user) { return mapper.InsertAll(user); } }
3)这是SpringBootMapper里面的代码:
public int InsertAll(User user); //后面的XML字段属性和User中的字段属性名是一样的,当方法名的参数是一个对象的时候
4)这是xml文件里面的代码:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.UserMapper.SpringBootMapper"> <insert id="InsertAll"> insert into User values(null,#{classID},#{username},#{password}) 这里面的字段名必须和对象的属性名是相同的 </insert> </mapper>
在写XML文件的时候,希望在url输入一个地址,里面的querystring就是user对象的值,但是我们在进行插入数据的时候,格式是#{Java代码中类的字段名}(对应着数据库的列名)
第二种:我们希望拿到插入数据之后的自增主键(返回自增id)
我们只需要更改xml文件里面的配置即可
下面我们对这里面添加的东西来做一个说明:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.UserMapper.SpringBootMapper"> <insert id="InsertAll" useGeneratedKeys="true" keyProperty="userID" keyColumn="userID"> insert into User values(null,#{classID},#{username},#{password}) </insert> </mapper>
1)useGeneratedKeys:这会令MyBatis使用JDBC的getGeneratedKeys方法来取出由数据库内部生成的主键,像MYSQL和SQL Server这样的数据库管理系统的自动递增字段,默认值是false
2)keyColumn:设置生成键值在数据库表中的列名,自增主键在数据库中的名字叫啥,当我们的数据库字段名和对象中的属性一样的时候,这个keyColumn是可以不用进行设置的,但是如果说数据库的字段名是id,对象中的属性名叫做UserID,这个时候就会进行自动设置的,自动把id的值赋值给User对象中的ID属性,所以方法的返回值是可以是void,也可以设置为int
3)keyProperties:指定对象中的属性,你返回的主键赋值到对象中的哪一个属性
我们还要注意:
调用数据库完成添加操作,执行完添加之后会将自增的userID指定到user上面的userID属性上面,因为我们进行添加操作的时候,我们是没有进行指定UserID的,是我们的数据库自己进行添加操作的,我们之前在XML里面进行设置的目的就是将我们进行成功插入之后,程序可以将我们的数据库生成的自增主键赋值到我们的user对象中的userID上面,然后我们再userController层上面就可以user的,userID属性了,如果我们的XML文件不进行设置的话,我们就此时返回的userID就不知道是啥值了;
1)UserController里面的代码: @Controller public class UserController { @Autowired UserService userService; @RequestMapping("/InsertAll") @ResponseBody public int InsertAll(User user) { //我们需要在UserController进行参数校验 if(user==null||user.equals("")) { return -1; } userService.InsertAll(user); return user.getUserID(); } } 2)UserService里面的代码: @Service public class UserService { @Autowired private SpringBootMapper mapper; public List<User> GetAll() { return mapper.GetAll(); } public int InsertAll(User user) { return mapper.InsertAll(user); } } 3)接口里面的代码: public int InsertAll(User user);
回顾单元测试:
1)定义:是指对软件中的最小可测试单元进行检查和验证的过程中就叫做单元测试,在咱们的SpringBoot中是测试某一个方法,可以非常简单直观,快速的测试某一项功能是否正确
单元测试是开发者编写的一小段代码,用于检测被测试代码一个很小的,很明确的代码功能是否执行正确,就是为了证明某段代码的执行是否符合我们的预期
2)单元测试的好处:
2.1)单元测试是不需要进行启动Tomact的非常简单的直观快速的测试某一个功能是否正确
2.2)还有就是说如果我们中途修改了代码,打包的时候就会自动的去执行单元测试,单元测试后错误就会被发现也就是说在我们打包之前所有的单元测试必须通过,否则不能打包成功
2.3)使用单元测试进行测试的时候,可以不污染连接的数据库,也就是说在不对数据库进行任何污染的情况下,测试功能,本质上是使用事务,进入方法之后开启事务,验证完方法之后,自动进行回滚;
创建SpringBoot单元测试:test文件夹是在src目录下的
咱们的SpringBoot项目创建的时候会默认单元测试框架spring-boot-test,而这个单元测试框架是依靠另一个著名的测试框架Junit来进行实现的,打开pom.xml就可以看到,这个依赖是SpringBoot项目自动添加的,所以说咱们的高版本的SpringBoot已经内置了一些框架,单元测试框架,JSON格式的处理ObjectMapper类Spring都已经内置好了,所以Spring是包含了众多工具方法的IOC容器;
1)创建准备条件:测试框架(默认已经添加)添加测试的目录,默认是已经被创建的;
2)在需要进行测试的类左边进行右键双击Generate生成,选择生成单元测试,生成测试类和测试的方法,点击test,ctrl+shift+T;
Testing library:单元测试框架,选择默认即可
ClassName:生成单元测试的类名也就是我们要进行测试的某一个类名后面加上test就可以了
Superclass:表示单元测试的父类,不需要直接设置,成空就可以了
Destination package:生成单元测试的目录,单元测试类要放在哪一个包底下,不需要修改
Generate:是否生成前置方法,执行测试方法之前的前一个方法或者后置方法,通常不会使用
这个前置方法和后置方法可以用来记录一下程序执行时间,配置单元测试的类,并添加单元测试的代码逻辑
Member:测试方法列表,你要测试哪一个方法,最后点击OK就行了测试的方法是一个空方法
3)要给当前类加上@SpringBootTest注解,声明当前的单元测试的类是在SpringBoot容器里面运行的,也就是说咱们要进行测试的类是一个SpringBoot;
4)在方法中构建咱们的测试代码,添加单元测试类的代码,并且可以属性注入;
5)@Transaction的好处就是执行完我们的单元测试代码之后可以进行回滚操作,就不会进行污染业务数据,不会污染原有的数据库,红色表示单元测试执行失败
@SpringBootTest @Transactional class UserControllerTest { @Autowired UserController userController; @Test void insertAll() { User user=new User(); user.setClassID(2); user.setUsername("白雪"); user.setPassword("我想吃饭"); int len=userController.InsertAll(user); Assertions.assertEquals(len,1);//比较它们是否相等,如果相等,说明单元测试过了,否则是不会过的 } }
下面来我们来使用一下单元测试的方式来进行验证一下插入操作返回的时候是主键ID
@SpringBootTest @Transactional class UserControllerTest { @Autowired UserController userController; //需要先注入UserController对象,调用里面的方法 @Test void insertAll() { User user=new User(); user.setClassID(3); user.setUsername("李佳鑫"); user.setPassword("生活要战斗"); int len= userController.InsertAll(user); Assertions.assertEquals(len,user.getUserID()); } }
程序报错---->程序直接爆红
测试不通过--->颜色变成橙色
测试通过---->直接变成蓝色
@Param里面的字段数据要和XML里面的数据要相同,一一对应,可以修改接口中的参数的别名,尽量写@param,尽量写@Param,会出现找不到参数的异常
@Transaction加上这个注解,就可以保证单元测试的数据不会污染到原来的数据
下面我们来实现以下修改操作:我想修改指定人名的密码:
我们此时一定要注意,修改的属性和名字和数据库中的名字和Java代码中的类的名字都是不一致的
http://127.0.0.1:8080/update?name=李佳伟&studentPassword=778896
上面是我们在浏览器上面输入的url
一:这是UserController里面的代码:
import java.util.List; @Controller public class UserController { @Autowired UserService userService; @RequestMapping("/update") @ResponseBody public int UpDate(String name,String studentPassword) { //我们首先要在Controller层进行参数校验 if(name==null||name.equals("")||studentPassword.equals("")||studentPassword==null) { return -1; } return userService.UpDate(name,studentPassword); } }
二:这是UserService里面的代码:
@Service public class UserService { @Autowired private SpringBootMapper mapper; public int UpDate(String name, String studentPassword) { return mapper.UpDate(name,studentPassword); } }
三:这是XML文件和接口中的代码:
int UpDate(String name, String studentPassword); <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.UserMapper.SpringBootMapper"> <update id="UpDate"> update user set password=#{studentPassword} where username=#{name} </update> </mapper>
我们使用单元测式的方式来进行检测:
@SpringBootTest @Transactional class UserControllerTest { @Autowired UserController userController; @Test void upDate() { int len= userController.UpDate("李佳伟","773377"); Assertions.assertEquals(len,1); } }
在接口文件里面添加方法的声明,在XML文件里面添加接口的实现标签和具体的执行的SQL
我们来实现一下删除操作:我们设想是通过浏览器传递的UserID来进行删除
1)在Mapper(Interface里面)添加删除的代码声明
2)在XML文件里面添加<delete>标签和删除的SQL编写
1)UserController里面的代码:
@Controller public class UserController { @Autowired UserService userService; @RequestMapping("/Delete") @ResponseBody public int Delete(Integer userID) { if(userID==null||userID.equals("")||userID<=0) { return -1; } return userService.Delete(userID); } }
2)UserService和Mapper里面的代码:
@Service public class UserService { @Autowired private SpringBootMapper mapper; public int Delete(Integer userID) { return mapper.Delete(userID); } } int Delete(Integer userID);
3)我们实现的XML文件的代码:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD com.example.demo.Mapper1 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.UserMapper.SpringBootMapper"> <delete id="Delete"> delete from user where userID=#{userID} </delete> </mapper>
使用单元测试的方式来进行测试我们的删除操作:
@SpringBootTest @Transactional class UserControllerTest { @Autowired UserController userController; @Test void delete() { int len= userController.Delete(1); }
1)在接口中可以写成这样:User run(@Param("userID") int userID);多加上一个注解 2)在线演示地址,linux服务器项目地址(在线演示地址,提供用户名和密码),源码地址(githup)(加上注释),(然后重要的技能放前面,学校等不占优势的放在后面)3)在进行查询的时候,一定要加上resultMap或者resultType,否则就会报500这样的错误,二者必选其一,但是update标签只需要设置id就可以;