Spring Boot点餐系统实战(2)–商品类目的Dao和Service层开发和测试

本文主要介绍商品类目(product_category表) 的Dao和Sercice层的开发,还有lombok 工具的使用,还有几个常用的注解,以及功能测试。

开始吧。

本文新关键词

lombok插件

@DynamicUpdate注解 

@Transactional注解

JpaRepository 接口方法命名规则

断言 

 

一、基本准备

1、数据表结构

我们说过,本文是介绍对商品类目表的增删改查,先看一些商品类目表的结构

Spring Boot点餐系统实战(2)–商品类目的Dao和Service层开发和测试

这是我之前测试时添加的数据

Spring Boot点餐系统实战(2)–商品类目的Dao和Service层开发和测试

 

2、导入数据库依赖,安装 lombok 插件

  1. <dependency>
  2.     <groupId>mysql</groupId>
  3.     <artifactId>mysql-connector-java</artifactId>
  4. </dependency>
  5. <dependency>
  6.     <groupId>org.springframework.boot</groupId>
  7.     <artifactId>spring-boot-starter-data-jpa</artifactId>
  8. </dependency>
  9. <dependency>
  10.     <groupId>org.projectlombok</groupId>
  11.     <artifactId>lombok</artifactId>
  12. </dependency>

前两个是数据库操作使用,第三个 lombok 是一个插件,可以帮我们在打包项目的时候自动生成 Setter/Getter,toString()方法之类的,而我们只需要在类上加一个注解,而不需要写那些冗余的代码。

要使用lombok,在引入上面的依赖后,还需要安装 IDEA 插件,

Spring Boot点餐系统实战(2)–商品类目的Dao和Service层开发和测试

 

3、文件结构

下面的是最终的文件结构

Spring Boot点餐系统实战(2)–商品类目的Dao和Service层开发和测试

我们一步步来讲解

 

二、实体类的创建

现在我们要创建 product_category 表的实体类,类名需要按照驼峰法,即 ProductCategory

ProductCategory.java

  1. package com.liuyanzhao.sell.entity;
  2. import org.hibernate.annotations.DynamicUpdate;
  3. import javax.persistence.Entity;
  4. import javax.persistence.GeneratedValue;
  5. import javax.persistence.Id;
  6. import java.util.Date;
  7. /**
  8.  * @Author: 言曌
  9.  * @Date: 2017/11/11
  10.  * @Time: 下午4:48
  11.  */
  12. @Entity
  13. @DynamicUpdate //可以让updateTime动态更新
  14. public class ProductCategory {
  15.     //类目id
  16.     @Id
  17.     @GeneratedValue
  18.     private Integer categoryId;
  19.     //类目名字
  20.     private String categoryName;
  21.     //类目编号
  22.     private Integer categoryType;
  23.     public ProductCategory() {
  24.     }
  25.     //创建时间
  26.     private Date createTime;
  27.     //更新时间
  28.     private Date updateTime;
  29.     public Integer getCategoryId() {
  30.         return categoryId;
  31.     }
  32.     public void setCategoryId(Integer categoryId) {
  33.         this.categoryId = categoryId;
  34.     }
  35.     public String getCategoryName() {
  36.         return categoryName;
  37.     }
  38.     public void setCategoryName(String categoryName) {
  39.         this.categoryName = categoryName;
  40.     }
  41.     public Integer getCategoryType() {
  42.         return categoryType;
  43.     }
  44.     public void setCategoryType(Integer categoryType) {
  45.         this.categoryType = categoryType;
  46.     }
  47.     public Date getCreateTime() {
  48.         return createTime;
  49.     }
  50.     public void setCreateTime(Date createTime) {
  51.         this.createTime = createTime;
  52.     }
  53.     public Date getUpdateTime() {
  54.         return updateTime;
  55.     }
  56.     public void setUpdateTime(Date updateTime) {
  57.         this.updateTime = updateTime;
  58.     }
  59.     @Override
  60.     public String toString() {
  61.         return "ProductCategory{" +
  62.                 "categoryId=" + categoryId +
  63.                 ", categoryName='" + categoryName + '\'' +
  64.                 ", categoryType=" + categoryType +
  65.                 '}';
  66.     }
  67. }

有木有感觉上面的代码有点多,特别是那个 Getter/Setter 方法太多了,每新建一个类,都需要加入 Getter/Setter 方法,如果修改某个属性类型的话,也需要修改。其实我们只需要使用之前说的 lombok 工具就可以解决这个问题。

在安装了 lombok 插件和 导入了 lombok 依赖后,我们的代码可以简化很多

ProductCategory.java

  1. package com.liuyanzhao.sell.entity;
  2. import lombok.Data;
  3. import org.hibernate.annotations.DynamicUpdate;
  4. import javax.persistence.Entity;
  5. import javax.persistence.GeneratedValue;
  6. import javax.persistence.Id;
  7. import java.util.Date;
  8. /**
  9.  * @Author: 言曌
  10.  * @Date: 2017/11/11
  11.  * @Time: 下午4:48
  12.  */
  13. @Entity
  14. @DynamicUpdate //可以让updateTime动态更新
  15. @Data //自动生成 Setter/Getter toString()
  16. public class ProductCategory {
  17.     //类目id
  18.     @Id
  19.     @GeneratedValue
  20.     private Integer categoryId;
  21.     //类目名字
  22.     private String categoryName;
  23.     //类目编号
  24.     private Integer categoryType;
  25.     //创建时间
  26.     private Date createTime;
  27.     //更新时间
  28.     private Date updateTime;
  29.     public ProductCategory() {
  30.     }
  31. }

 

 

更多补充

1、@Entity 注解

表示该类是一个实体类

 

2、@DynamicUpdate  注解

可以动态更新数据表中那些需要更新的字段,比如我们的 updateTime 这个属性对应的是数据表中 update_time 字段,这个字段虽然在数据库里写了自动更新的代码,即

  1. `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',

但是,在这里,如果你对记录更新的时候,没有给 updateTime 属性赋值,它是不会改变的,这时我们不想看到的。

如果我们给这个类加上 @DynamicUpdate  注解,那么我们的 update_time 字段就会随更改时间而改变了。

 

3、@Data 注解

该注解是 lombok 的

@Data 包含了@ToString,@EqualsAndHashCode,@Getter / @Setter和@RequiredArgsConstructor的功能

 

4、@Id 注解

表示该属性为主键

 

5、@GeneratedValue

表示该属性自动生成值,这里指 的是 id 的值自增

 

6、无参的构造方法

正常情况,系统会默认生成一个无参的构造方法,也就是说我们这里其实是不需要写的。但是为了防止今后添加了有参的构造(此时系统不会默认生成无参的),忘记添加了无参的构造,导致报错。

总之,记得,无参的构造方法必不可少啦啦。

 

三、Dao 层的创建

新建一个 ProductCategoryDao 类,这个类名倒是无所谓,你也可以叫 ProductCategoryRepository

ProductCategoryDao.java

  1. package com.liuyanzhao.sell.dao;
  2. import com.liuyanzhao.sell.entity.ProductCategory;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. import java.util.List;
  5. /**
  6.  * @Author: 言曌
  7.  * @Date: 2017/11/11
  8.  * @Time: 下午4:52
  9.  */
  10. public interface ProductCategoryDao extends JpaRepository<ProductCategory,Integer> {
  11.     List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryTypeList);
  12. }

因为本项目使用的是Spring Data JPA 对数据库操作,而且十分方便。

这里需要继承 JpaRepository 接口,这是一个访问数据库模型的超级接口

JpaRepository<参数1,参数2> 其中参数1表示是对哪个实体(数据表)操作,参数2表示是该实体的主键属性类型。

我们继承了 JpaRepository 接口,就有了很多常用的对数据库增删改查的方法

具体有哪些方法呢?我们查看一下源码,最终找到 CrudRepository 接口

Spring Boot点餐系统实战(2)–商品类目的Dao和Service层开发和测试

有如上方法,当然不同的方法有携带不同类型的参数的多态。

 

通常上面的方法还是不够我们使用,我们需要自定义一些方法。

比如我们要根据一个分类类型的列表查询一个列表的分类信息。

  1. List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryTypeList);

我们只需要写如上的接口方法,记住不需要我们写它的实现方法,系统会帮我们做,所以方法名很重要,不能错。

参考这个表格

关键字 方法命名 sql where字句
And findByNameAndPwd where name= ? and pwd =?
Or findByNameOrSex where name= ? or sex=?
Is,Equals findById,findByIdEquals where id= ?
Between findByIdBetween where id between ? and ?
LessThan findByIdLessThan where id < ?
LessThanEquals findByIdLessThanEquals where id <= ?
GreaterThan findByIdGreaterThan where id > ?
GreaterThanEquals findByIdGreaterThanEquals where id > = ?
After findByIdAfter where id > ?
Before findByIdBefore where id < ?
IsNull findByNameIsNull where name is null
isNotNull,NotNull findByNameNotNull where name is not null
Like findByNameLike where name like ?
NotLike findByNameNotLike where name not like ?
StartingWith findByNameStartingWith where name like '?%'
EndingWith findByNameEndingWith where name like '%?'
Containing findByNameContaining where name like '%?%'
OrderBy findByIdOrderByXDesc where id=? order by x desc
Not findByNameNot where name <> ?
In findByIdIn(Collection<?> c) where id in (?)
NotIn findByIdNotIn(Collection<?> c) where id not  in (?)
True findByAaaTue where aaa = true
False findByAaaFalse where aaa = false
IgnoreCase findByNameIgnoreCase where UPPER(name)=UPPER(?)

 

 

四、测试 Dao 层的方法

在 Test 中新建 ProductCategoryDaoTest.java,或者直接使用 IDEA ,点击某个类名或接口名,右键选择 Go To,点击 Test,快速生成 Test 测试类。

我们对几个会用到的方法进行测试

  1. package com.liuyanzhao.sell.dao;
  2. import com.liuyanzhao.sell.entity.ProductCategory;
  3. import org.junit.Assert;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. import org.springframework.transaction.annotation.Transactional;
  10. import java.util.Arrays;
  11. import java.util.List;
  12. /**
  13.  * @Author: 言曌
  14.  * @Date: 2017/11/11
  15.  * @Time: 下午4:54
  16.  */
  17. @RunWith(SpringRunner.class)
  18. @SpringBootTest
  19. public class ProductCategoryDaoTest {
  20.     @Autowired
  21.     private ProductCategoryDao dao;
  22.     @Test
  23.     public void findOneTest() {
  24.         ProductCategory productCategory = dao.findOne(1);
  25.         System.out.println(productCategory);
  26.     }
  27.     @Test
  28.     @Transactional //不在数据库中添加测试数据
  29.     public void saveTest() {
  30.         ProductCategory productCategory = new ProductCategory();
  31.         productCategory.setCategoryName("零食");
  32.         productCategory.setCategoryType(3);
  33.         ProductCategory result = dao.save(productCategory);
  34.         //使用断言判断
  35.         Assert.assertNotNull(result);
  36.         //Assert.assertNotEquals(null,result);//与上面效果一样
  37.     }
  38.     @Test
  39.     public void updateTest() {
  40.         ProductCategory productCategory = dao.findOne(2);
  41.         productCategory.setCategoryName("饮料");
  42.         productCategory.setCategoryType(5);
  43.         dao.save(productCategory);
  44.     }
  45.     @Test
  46.     public void findByCategoryTypeInTest() {
  47.         List<Integer> list = Arrays.asList(1,2,3);
  48.         List<ProductCategory> result = dao.findByCategoryTypeIn(list);
  49.         Assert.assertNotEquals(0,result.size());
  50.     }
  51. }

 

其他补充

1、测试类需要加两个注解

@RunWith(SpringRunner.class)

@SpringBootTest

 

2、使用断言

我们这里使用断言来验证,如果断言错误,则会无法通过 Test

 

3、@Transactional  注解

因为我们通常的测试都是会在数据库中生成记录的,比如 save方法会创建一条记录,update方法修改记录。如果我们不想测试的时候在数据库里乱加内容,我们可以使用 @Transactional 注解哦。

这是测试不通过的效果

Spring Boot点餐系统实战(2)–商品类目的Dao和Service层开发和测试

这是测试通过的效果

Spring Boot点餐系统实战(2)–商品类目的Dao和Service层开发和测试

 

 

五、Service 层的创建

1、创建 CategoryService 接口

CategoryService.java

  1. package com.liuyanzhao.sell.service;
  2. import com.liuyanzhao.sell.entity.ProductCategory;
  3. import java.util.List;
  4. /**
  5.  * @Author: 言曌
  6.  * @Date: 2017/11/11
  7.  * @Time: 下午6:50
  8.  */
  9. public interface CategoryService {
  10.     //查询一条记录
  11.     ProductCategory findOne(Integer categoryId);
  12.     //查询所有记录
  13.     List<ProductCategory> findAll();
  14.     //查询分类列表的分类
  15.     List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryTypeList);
  16.     //添加分类
  17.     ProductCategory save(ProductCategory productCategory);
  18. }

 

2、创建 CategoryService 实现类

  1. package com.liuyanzhao.sell.service.impl;
  2. import com.liuyanzhao.sell.dao.ProductCategoryDao;
  3. import com.liuyanzhao.sell.entity.ProductCategory;
  4. import com.liuyanzhao.sell.service.CategoryService;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Service;
  7. import java.util.List;
  8. /**
  9.  * @Author: 言曌
  10.  * @Date: 2017/11/11
  11.  * @Time: 下午7:04
  12.  */
  13. @Service
  14. public class CategoryServiceImpl implements CategoryService {
  15.     @Autowired
  16.     private ProductCategoryDao dao;
  17.     @Override
  18.     public ProductCategory findOne(Integer categoryId) {
  19.         return dao.findOne(categoryId);
  20.     }
  21.     @Override
  22.     public List<ProductCategory> findAll() {
  23.         return dao.findAll();
  24.     }
  25.     @Override
  26.     public List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryTypeList) {
  27.         return dao.findByCategoryTypeIn(categoryTypeList);
  28.     }
  29.     @Override
  30.     public ProductCategory save(ProductCategory productCategory) {
  31.         return dao.save(productCategory);
  32.     }
  33. }

 

这里的代码都不需要解释了吧

 

六、Service 层的测试

新建 CategoryServiceImplTest.java

  1. package com.liuyanzhao.sell.service.impl;
  2. import com.liuyanzhao.sell.entity.ProductCategory;
  3. import org.junit.Assert;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. import java.util.Arrays;
  10. import java.util.List;
  11. import static org.junit.Assert.*;
  12. /**
  13.  * @Author: 言曌
  14.  * @Date: 2017/11/11
  15.  * @Time: 下午7:07
  16.  */
  17. @RunWith(SpringRunner.class)
  18. @SpringBootTest
  19. public class CategoryServiceImplTest {
  20.     @Autowired
  21.     private CategoryServiceImpl categoryService;
  22.     @Test
  23.     public void findOne() throws Exception {
  24.         ProductCategory productCategory = categoryService.findOne(1);
  25.         Assert.assertEquals(new Integer(1),productCategory.getCategoryId());
  26.     }
  27.     @Test
  28.     public void findAll() throws Exception {
  29.         List<ProductCategory> productCategoryList = categoryService.findAll();
  30.         Assert.assertNotEquals(0,productCategoryList.size());
  31.     }
  32.     @Test
  33.     public void findByCategoryTypeIn() throws Exception {
  34.         List<ProductCategory> productCategoryList = categoryService.findByCategoryTypeIn(Arrays.asList(1,2,3));
  35.         Assert.assertNotEquals(0,productCategoryList.size());
  36.     }
  37.     @Test
  38.     public void save() throws Exception {
  39.         ProductCategory productCategory = new ProductCategory();
  40.         productCategory.setCategoryName("酒类");
  41.         productCategory.setCategoryType(5);
  42.         ProductCategory result = categoryService.save(productCategory);
  43.         Assert.assertNotNull(result);
  44.     }
  45. }

 

这里也没啥好讲的,和之前 Dao 层测试类似。

记住注入的是 CategoryServiceImpl 就行了。

 

本文链接:https://liuyanzhao.com/6632.html

  • 微信
  • 交流学习,有偿服务
  • weinxin
  • 博客/Java交流群
  • 资源分享,问题解决,技术交流。群号:590480292
  • weinxin
言曌

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: