学生信息管理系统_项目学生:业务层

学生信息管理系统

学生信息管理系统

这是Project Student的一部分。 其他职位包括带有Jersey的Webservice Client,带有Jersey的Webservice Server带有Spring Data的Persistence

RESTful Webapp洋葱的第三层是业务层。 这就是应用程序的精髓所在–编写良好的持久性和Web服务层受到约束,但是任何事情都在业务层中进行。

此时我们仅实现CRUD方法,因此这些方法非常简单。

设计决策

Spring Data –我们将使用Spring Data作为持久层,因此我们需要牢记指定持久层接口。 正如我们将在下一个博客中看到的那样,这极大地简化了我们的生活。

局限性

DataAccessException –不会根据我们收到的DataAccessException的类型尝试抛出不同的异常。 稍后这将很重要–我们应该以不同于丢失数据库连接的方式对待约束违反。

服务介面

首先提醒我们在上一篇文章中确定的服务接口。

public interface CourseService {
    List<Course> findAllCourses();

    Course findCourseById(Integer id);

    Course findCourseByUuid(String uuid);

    Course createCourse(String name);

    Course updateCourse(Course course, String name);

    void deleteCourse(String uuid);
}

服务实施

由于服务是基本的CRUD操作,因此该服务的实施速度很快。 我们唯一关心的是数据库是否存在问题(Spring中的DataAccessException)或找不到期望值。 我们需要在前者的API中添加新的例外,而后者的API中已经有例外。

public class CourseServiceImpl implements CourseService {
    private static final Logger log = LoggerFactory
            .getLogger(CourseServiceImpl.class);

    @Resource
    private CourseRepository courseRepository;

    /**
     * Default constructor
     */
    public CourseServiceImpl() {

    }

    /**
     * Constructor used in unit tests
     */
    CourseServiceImpl(CourseRepository courseRepository) {
        this.courseRepository = courseRepository;
    }

    /**
     * @see com.invariantproperties.sandbox.student.business.CourseService#
     *      findAllCourses()
     */
    @Transactional(readOnly = true)
    @Override
    public List<Course> findAllCourses() {
        List<Course> courses = null;

        try {
            courses = courseRepository.findAll();
        } catch (DataAccessException e) {
            if (!(e instanceof UnitTestException)) {
                log.info("error loading list of courses: " + e.getMessage(), e);
            }
            throw new PersistenceException("unable to get list of courses.", e);
        }

        return courses;
    }

    /**
     * @see com.invariantproperties.sandbox.student.business.CourseService#
     *      findCourseById(java.lang.Integer)
     */
    @Transactional(readOnly = true)
    @Override
    public Course findCourseById(Integer id) {
        Course course = null;
        try {
            course = courseRepository.findOne(id);
        } catch (DataAccessException e) {
            if (!(e instanceof UnitTestException)) {
                log.info("internal error retrieving course: " + id, e);
            }
            throw new PersistenceException("unable to find course by id", e, id);
        }

        if (course == null) {
            throw new ObjectNotFoundException(id);
        }

        return course;
    }

    /**
     * @see com.invariantproperties.sandbox.student.business.CourseService#
     *      findCourseByUuid(java.lang.String)
     */
    @Transactional(readOnly = true)
    @Override
    public Course findCourseByUuid(String uuid) {
        Course course = null;
        try {
            course = courseRepository.findCourseByUuid(uuid);
        } catch (DataAccessException e) {
            if (!(e instanceof UnitTestException)) {
                log.info("internal error retrieving course: " + uuid, e);
            }
            throw new PersistenceException("unable to find course by uuid", e,
                    uuid);
        }

        if (course == null) {
            throw new ObjectNotFoundException(uuid);
        }

        return course;
    }

    /**
     * @see com.invariantproperties.sandbox.student.business.CourseService#
     *      createCourse(java.lang.String)
     */
    @Transactional
    @Override
    public Course createCourse(String name) {
        final Course course = new Course();
        course.setName(name);

        Course actual = null;
        try {
            actual = courseRepository.saveAndFlush(course);
        } catch (DataAccessException e) {
            if (!(e instanceof UnitTestException)) {
                log.info("internal error retrieving course: " + name, e);
            }
            throw new PersistenceException("unable to create course", e);
        }

        return actual;
    }

    /**
     * @see com.invariantproperties.sandbox.course.persistence.CourseService#
     *      updateCourse(com.invariantproperties.sandbox.course.domain.Course,
     *      java.lang.String)
     */
    @Transactional
    @Override
    public Course updateCourse(Course course, String name) {
        Course updated = null;
        try {
            final Course actual = courseRepository.findCourseByUuid(course
                    .getUuid());

            if (actual == null) {
                log.debug("did not find course: " + course.getUuid());
                throw new ObjectNotFoundException(course.getUuid());
            }

            actual.setName(name);
            updated = courseRepository.saveAndFlush(actual);
            course.setName(name);

        } catch (DataAccessException e) {
            if (!(e instanceof UnitTestException)) {
                log.info("internal error deleting course: " + course.getUuid(),
                        e);
            }
            throw new PersistenceException("unable to delete course", e,
                    course.getUuid());
        }

        return updated;
    }

    /**
     * @see com.invariantproperties.sandbox.student.business.CourseService#
     *      deleteCourse(java.lang.String)
     */
    @Transactional
    @Override
    public void deleteCourse(String uuid) {
        Course course = null;
        try {
            course = courseRepository.findCourseByUuid(uuid);

            if (course == null) {
                log.debug("did not find course: " + uuid);
                throw new ObjectNotFoundException(uuid);
            }
            courseRepository.delete(course);

        } catch (DataAccessException e) {
            if (!(e instanceof UnitTestException)) {
                log.info("internal error deleting course: " + uuid, e);
            }
            throw new PersistenceException("unable to delete course", e, uuid);
        }
    }
}

此实现告诉我们持久层所需的接口。

持久层接口

我们将使用Spring Data作为持久层,并且DAO接口与Spring Data存储库相同。 我们只需要一种非标准方法。

public class CourseServiceImplTest {

    @Test
    public void testFindAllCourses() {
        final List<Course> expected = Collections.emptyList();

        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findAll()).thenReturn(expected);

        final CourseService service = new CourseServiceImpl(repository);
        final List<Course> actual = service.findAllCourses();

        assertEquals(expected, actual);
    }

    @Test(expected = PersistenceException.class)
    public void testFindAllCoursesError() {
        final List<Course> expected = Collections.emptyList();

        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findAll()).thenThrow(new UnitTestException());

        final CourseService service = new CourseServiceImpl(repository);
        final List<Course> actual = service.findAllCourses();

        assertEquals(expected, actual);
    }

    @Test
    public void testFindCourseById() {
        final Course expected = new Course();
        expected.setId(1);

        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findOne(any(Integer.class))).thenReturn(expected);

        final CourseService service = new CourseServiceImpl(repository);
        final Course actual = service.findCourseById(expected.getId());

        assertEquals(expected, actual);
    }

    @Test(expected = ObjectNotFoundException.class)
    public void testFindCourseByIdMissing() {
        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findOne(any(Integer.class))).thenReturn(null);

        final CourseService service = new CourseServiceImpl(repository);
        service.findCourseById(1);
    }

    @Test(expected = PersistenceException.class)
    public void testFindCourseByIdError() {
        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findOne(any(Integer.class))).thenThrow(
                new UnitTestException());

        final CourseService service = new CourseServiceImpl(repository);
        service.findCourseById(1);
    }

    @Test
    public void testFindCourseByUuid() {
        final Course expected = new Course();
        expected.setUuid("[uuid]");

        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findCourseByUuid(any(String.class))).thenReturn(
                expected);

        final CourseService service = new CourseServiceImpl(repository);
        final Course actual = service.findCourseByUuid(expected.getUuid());

        assertEquals(expected, actual);
    }

    @Test(expected = ObjectNotFoundException.class)
    public void testFindCourseByUuidMissing() {
        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findCourseByUuid(any(String.class))).thenReturn(null);

        final CourseService service = new CourseServiceImpl(repository);
        service.findCourseByUuid("[uuid]");
    }

    @Test(expected = PersistenceException.class)
    public void testFindCourseByUuidError() {
        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findCourseByUuid(any(String.class))).thenThrow(
                new UnitTestException());

        final CourseService service = new CourseServiceImpl(repository);
        service.findCourseByUuid("[uuid]");
    }

    @Test
    public void testCreateCourse() {
        final Course expected = new Course();
        expected.setName("name");
        expected.setUuid("[uuid]");

        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.saveAndFlush(any(Course.class))).thenReturn(expected);

        final CourseService service = new CourseServiceImpl(repository);
        final Course actual = service.createCourse(expected.getName());

        assertEquals(expected, actual);
    }

    @Test(expected = PersistenceException.class)
    public void testCreateCourseError() {
        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.saveAndFlush(any(Course.class))).thenThrow(
                new UnitTestException());

        final CourseService service = new CourseServiceImpl(repository);
        service.createCourse("name");
    }

    @Test
    public void testUpdateCourse() {
        final Course expected = new Course();
        expected.setName("Alice");
        expected.setUuid("[uuid]");

        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findCourseByUuid(any(String.class))).thenReturn(
                expected);
        when(repository.saveAndFlush(any(Course.class))).thenReturn(expected);

        final CourseService service = new CourseServiceImpl(repository);
        final Course actual = service.updateCourse(expected, "Bob");

        assertEquals("Bob", actual.getName());
    }

    @Test(expected = ObjectNotFoundException.class)
    public void testUpdateCourseMissing() {
        final Course expected = new Course();
        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findCourseByUuid(any(String.class))).thenReturn(null);

        final CourseService service = new CourseServiceImpl(repository);
        service.updateCourse(expected, "Bob");
    }

    @Test(expected = PersistenceException.class)
    public void testUpdateCourseError() {
        final Course expected = new Course();
        expected.setUuid("[uuid]");

        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findCourseByUuid(any(String.class))).thenReturn(
                expected);
        doThrow(new UnitTestException()).when(repository).saveAndFlush(
                any(Course.class));

        final CourseService service = new CourseServiceImpl(repository);
        service.updateCourse(expected, "Bob");
    }

    @Test
    public void testDeleteCourse() {
        final Course expected = new Course();
        expected.setUuid("[uuid]");

        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findCourseByUuid(any(String.class))).thenReturn(
                expected);
        doNothing().when(repository).delete(any(Course.class));

        final CourseService service = new CourseServiceImpl(repository);
        service.deleteCourse(expected.getUuid());
    }

    @Test(expected = ObjectNotFoundException.class)
    public void testDeleteCourseMissing() {
        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findCourseByUuid(any(String.class))).thenReturn(null);

        final CourseService service = new CourseServiceImpl(repository);
        service.deleteCourse("[uuid]");
    }

    @Test(expected = PersistenceException.class)
    public void testDeleteCourseError() {
        final Course expected = new Course();
        expected.setUuid("[uuid]");

        final CourseRepository repository = Mockito
                .mock(CourseRepository.class);
        when(repository.findCourseByUuid(any(String.class))).thenReturn(
                expected);
        doThrow(new UnitTestException()).when(repository).delete(
                any(Course.class));

        final CourseService service = new CourseServiceImpl(repository);
        service.deleteCourse(expected.getUuid());
    }
}

整合测试

集成测试已推迟到实现持久层。

源代码

参考:项目学生:来自Invariant Properties博客的JCG合作伙伴Bear Giles的业务层

翻译自: https://www.javacodegeeks.com/2014/01/project-student-business-layer.html

学生信息管理系统

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值