jpa中::::_项目学生:JPA标准查询
jpa中::::
这是Project Student的一部分。 其他职位包括带有Jersey的Webservice Client,带有Jersey的 Webservice Server , 业务层 , 具有Spring Data的持久性 ,分片集成测试数据和Webservice Integration 。
我们已经介绍了CRUD的基本操作,但是并没有花太多时间。 Spring Data使包含基本搜索变得容易,但是拥有其他标准选项也很重要。 JPA标准查询是最重要的查询之一。
Spring Data JPA教程– JPA Criteria Queries [http://www.petrikainulainen.net]是对该材料的很好介绍。
设计决策
JPA标准 –我使用的是JPA标准搜索,而不是querydsl。 稍后我将返回querydsl。
局限性
违反封装 –此设计需要打破使每个层完全不了解其他层的实现细节的体系结构目标。 这是一个非常小的违反行为-仅JPA规范-我们仍然必须处理分页。 将它们放在一起,我觉得此时过分担心这个还为时过早。
Web服务 -不更新web服务客户端和服务器。 同样,我们仍然必须处理分页,并且无论如何我们现在要做的任何事情都必须更改。
重构先前的工作
我对以前的工作有三点改变。
findCoursesByTestRun()
我已经定义了方法:
List findCoursesByTestRun(TestRun testRun);
在课程库中。 那没有预期的效果。 我需要的是
List findCoursesByTestRun_Uuid(String uuid);
对调用代码进行适当的更改。 或者,您可以只使用下面讨论的JPA条件查询。
FinderService和ManagerService
这来自Jumpstart网站上的研究。 作者将标准服务接口分为两部分:
- FinderService –只读操作(搜索)
- ManagerService –读写操作(创建,更新,删除)
这很有道理,例如,当我们可以在类与方法级别上进行操作时,通过AOP添加行为会容易得多。 我在现有代码中做了适当的更改。
查找错误
我已经修复了FindBugs发现的许多问题。
元数据
我们首先允许对持久对象的元数据访问。 这使我们能够创建可以通过JPA实现进行优化的查询。
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;@StaticMetamodel(Course.class)
public class Course_ {public static volatile SingularAttribute<Course, TestRun> testRun;
}
和
@StaticMetamodel(TestRun.class)
public class TestRun_ {public static volatile SingularAttribute<TestRun, String> uuid;
}
由于约定优于配置,因此需要类的名称。
- 有关此功能的讨论,请参见静态元数据 [jboss.org]。
技术指标
现在,我们可以使用现在可用的元数据创建查询规范。 这是一个稍微复杂的查询,因为我们需要深入研究结构。 (这不需要实际的联接,因为testrun uuid用作外键。)
public class CourseSpecifications {/*** Creates a specification used to find courses with the specified testUuid.* * @param testRun* @return*/public static Specification<Course> testRunIs(final TestRun testRun) {return new Specification<Course>() {@Overridepublic Predicate toPredicate(Root<Course> courseRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {Predicate p = null;if (testRun == null || testRun.getUuid() == null) {p = cb.isNull(courseRoot.<Course_> get("testRun"));} else {p = cb.equal(courseRoot.<Course_> get("testRun").<TestRun_> get("uuid"), testRun.getUuid());}return p;}};}
}
一些文档建议我可以使用get(Course_.testRun)代替get(“ testRun”),但是eclipse在get()方法上将其标记为类型冲突。 你的旅费可能会改变。
Spring数据仓库
我们必须告诉Spring Data我们正在使用JPA Criteria查询。 这是通过扩展JpaSpecificationExecutor接口来完成的。
@Repository
public interface CourseRepository extends JpaRepository<Course, Integer>,JpaSpecificationExecutor<Course> {Course findCourseByUuid(String uuid);List findCoursesByTestRunUuid(String uuid);
}
FinderService实施
现在,我们可以在我们的服务实现中使用JPA规范。 如上所述,使用JPA Criteria Specification违反了封装。
import static com.invariantproperties.sandbox.student.specification.CourseSpecifications.testRunIs;@Service
public class CourseFinderServiceImpl implements CourseFinderService {@Resourceprivate CourseRepository courseRepository;/*** @see com.invariantproperties.sandbox.student.business.FinderService#* count()*/@Transactional(readOnly = true)@Overridepublic long count() {return countByTestRun(null);}/*** @see com.invariantproperties.sandbox.student.business.FinderService#* countByTestRun(com.invariantproperties.sandbox.student.domain.TestRun)*/@Transactional(readOnly = true)@Overridepublic long countByTestRun(TestRun testRun) {long count = 0;try {count = courseRepository.count(testRunIs(testRun));} catch (DataAccessException e) {if (!(e instanceof UnitTestException)) {log.info("internal error retrieving classroom count by " + testRun, e);}throw new PersistenceException("unable to count classrooms by " + testRun, e, 0);}return count;}/*** @see com.invariantproperties.sandbox.student.business.CourseFinderService#* findAllCourses()*/@Transactional(readOnly = true)@Overridepublic List<Course> findAllCourses() {return findCoursesByTestRun(null);}/*** @see com.invariantproperties.sandbox.student.business.CourseFinderService#* findCoursesByTestRun(java.lang.String)*/@Transactional(readOnly = true)@Overridepublic List<Course> findCoursesByTestRun(TestRun testRun) {List<Course> courses = null;try {courses = courseRepository.findAll(testRunIs(testRun));} 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;}....
}
单元测试
我们的单元测试需要稍做更改才能使用规范。
public class CourseFinderServiceImplTest {private final Class<Specification<Course>> sClass = null;@Testpublic void testCount() {final long expected = 3;final CourseRepository repository = Mockito.mock(CourseRepository.class);when(repository.count(any(sClass))).thenReturn(expected);final CourseFinderService service = new CourseFinderServiceImpl(repository);final long actual = service.count();assertEquals(expected, actual);}@Testpublic void testCountByTestRun() {final long expected = 3;final TestRun testRun = new TestRun();final CourseRepository repository = Mockito.mock(CourseRepository.class);when(repository.count(any(sClass))).thenReturn(expected);final CourseFinderService service = new CourseFinderServiceImpl(repository);final long actual = service.countByTestRun(testRun);assertEquals(expected, actual);}@Test(expected = PersistenceException.class)public void testCountError() {final CourseRepository repository = Mockito.mock(CourseRepository.class);when(repository.count(any(sClass))).thenThrow(new UnitTestException());final CourseFinderService service = new CourseFinderServiceImpl(repository);service.count();}@Testpublic void testFindAllCourses() {final List<Course> expected = Collections.emptyList();final CourseRepository repository = Mockito.mock(CourseRepository.class);when(repository.findAll(any(sClass))).thenReturn(expected);final CourseFinderService service = new CourseFinderServiceImpl(repository);final List<Course> actual = service.findAllCourses();assertEquals(expected, actual);}@Test(expected = PersistenceException.class)public void testFindAllCoursesError() {final CourseRepository repository = Mockito.mock(CourseRepository.class);final Class<Specification<Course>> sClass = null;when(repository.findAll(any(sClass))).thenThrow(new UnitTestException());final CourseFinderService service = new CourseFinderServiceImpl(repository);service.findAllCourses();}@Testpublic void testFindCourseByTestUuid() {final TestRun testRun = new TestRun();final Course course = new Course();final List<Course> expected = Collections.singletonList(course);final CourseRepository repository = Mockito.mock(CourseRepository.class);when(repository.findAll(any(sClass))).thenReturn(expected);final CourseFinderService service = new CourseFinderServiceImpl(repository);final List actual = service.findCoursesByTestRun(testRun);assertEquals(expected, actual);}@Test(expected = PersistenceException.class)public void testFindCourseByTestUuidError() {final TestRun testRun = new TestRun();final CourseRepository repository = Mockito.mock(CourseRepository.class);when(repository.findAll(any(sClass))).thenThrow(new UnitTestException());final CourseFinderService service = new CourseFinderServiceImpl(repository);service.findCoursesByTestRun(testRun);}@Testpublic void testFindCoursesByTestUuid() {final TestRun testRun = new TestRun();final Course course = new Course();final List<Course> expected = Collections.singletonList(course);final CourseRepository repository = Mockito.mock(CourseRepository.class);when(repository.findAll(any(sClass))).thenReturn(expected);final CourseFinderService service = new CourseFinderServiceImpl(repository);final List<Course> actual = service.findCoursesByTestRun(testRun);assertEquals(expected, actual);}@Test(expected = PersistenceException.class)public void testFindCoursesByTestUuidError() {final TestRun testRun = new TestRun();final CourseRepository repository = Mockito.mock(CourseRepository.class);when(repository.findAll(any(sClass))).thenThrow(new UnitTestException());final CourseFinderService service = new CourseFinderServiceImpl(repository);service.findCoursesByTestRun(testRun);}....
}
通过使用@Begin方法,我可以消除很多重复的代码,但是我决定反对它来支持并行测试。
整合测试
我们终于来进行集成测试。 我们知道我们做对了,因为唯一的一行可以测试附加功能-计算数据库中的课程数量。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { BusinessApplicationContext.class, TestBusinessApplicationContext.class,TestPersistenceJpaConfig.class })
@Transactional
@TransactionConfiguration(defaultRollback = true)
public class CourseServiceIntegrationTest {@Resourceprivate CourseFinderService fdao;@Resourceprivate CourseManagerService mdao;@Resourceprivate TestRunService testService;@Testpublic void testCourseLifecycle() throws Exception {final TestRun testRun = testService.createTestRun();final String name = "Calculus 101 : " + testRun.getUuid();final Course expected = new Course();expected.setName(name);assertNull(expected.getId());// create courseCourse actual = mdao.createCourseForTesting(name, testRun);expected.setId(actual.getId());expected.setUuid(actual.getUuid());expected.setCreationDate(actual.getCreationDate());assertThat(expected, equalTo(actual));assertNotNull(actual.getUuid());assertNotNull(actual.getCreationDate());// get course by idactual = fdao.findCourseById(expected.getId());assertThat(expected, equalTo(actual));// get course by uuidactual = fdao.findCourseByUuid(expected.getUuid());assertThat(expected, equalTo(actual));// get all coursesfinal List<Course> courses = fdao.findCoursesByTestRun(testRun);assertTrue(courses.contains(actual));// count coursesfinal long count = fdao.countByTestRun(testRun);assertTrue(count > 0);// update courseexpected.setName("Calculus 102 : " + testRun.getUuid());actual = mdao.updateCourse(actual, expected.getName());assertThat(expected, equalTo(actual));// delete Coursemdao.deleteCourse(expected.getUuid(), 0);try {fdao.findCourseByUuid(expected.getUuid());fail("exception expected");} catch (ObjectNotFoundException e) {// expected}testService.deleteTestRun(testRun.getUuid());}
}
源代码
- 可从http://code.google.com/p/invariant-properties-blog/source/browse/student获取源代码。
翻译自: https://www.javacodegeeks.com/2014/01/project-student-jpa-criteria-queries.html
jpa中::::
jpa中::::_项目学生:JPA标准查询相关推荐
- 集成测试还原数据库_项目学生:分片集成测试数据
集成测试还原数据库 这是Project Student的一部分. 其他职位包括带有Jersey的Webservice Client,带有Jersey的 Webservice Server , 业务层和 ...
- web 项目集成福昕_项目学生:Web服务集成
web 项目集成福昕 这是Project Student的一部分. 其他帖子包括带有Jersey的 Web服务 客户端,带有Jersey的 Web服务服务器 , 业务层 , 具有Spring数据的持久 ...
- spring 事务持久性_项目学生:Spring数据的持久性
spring 事务持久性 这是Project Student的一部分. 其他职位包括带有Jersey的Webservice Client,带有Jersey的 Webservice Server和业务层 ...
- jersey put 服务_项目学生:带有Jersey的Web服务服务器
jersey put 服务 这是Project Student的一部分. 其他职位包括带有Jersey的Webservice Client , 业务层和带有Spring Data的持久性 . REST ...
- aop 代码_项目学生:使用AOP简化代码
aop 代码 这是Project Student的一部分. 许多人坚信方法应适合您的编辑器窗口(例如20行),而有些人认为方法应小于此范围. 这个想法是一种方法应该做一件事,而只能做一件事. 如果它做 ...
- 编程填空:学生信息处理程序_项目学生:业务层
编程填空:学生信息处理程序 这是Project Student的一部分. 其他职位包括带有Jersey的Webservice Client,带有Jersey的 Webservice Server和带有 ...
- mysql忽略大小写jpa解决_春数据JPA查询生成忽略大小写,以避免列数据
我使用的是春天的数据JPA获取使用ignoreCase属性数据为大写:春数据JPA查询生成忽略大小写,以避免列数据 Employee类: import javax.persistence.Entity ...
- ssm把图片保存到项目中_项目中的图片跨域问题解决方式
现象 首先,在生产环境中,由于进行编辑图片时,将图片回显到ReactCrop组件中进行可裁剪编辑,然而回显时,需要将图片转化为base64的格式或者blob对象, 此时需要将图片次绘制成canvas进 ...
- jersey客户端_项目学生:带有Jersey的Web服务客户端
jersey客户端 这是Project Student的一部分. 其他职位包括带有Jersey的Webservice Client, 带有Spring Data的 业务层和持久性 . RESTful ...
最新文章
- pinctrl框架【转】
- Android P 电量管理,Android P亮点汇总:更智能 更简单
- C# WinForm给Button按钮或其它控件添加快捷键响应
- 1080解析 芒果tv_国内主流视频平台解析下载观看
- Quick BI 的模型设计与生成SQL原理剖析
- 立足前沿 直击热点 搭建平台,2018中国人工智能大会在深圳拉开帷幕
- WindowsPhone7开发简单豆瓣网应用程序之界面设计
- [react] 在react中页面重新加载时怎样保留数据?
- Jython中文乱码问题
- Qt3D文档阅读笔记-Qt3D老版本知识点及使用新版本的运行
- mysql 14.12_[mysql] 14.12 innodb下的 磁盘I/O与文件空间管理方式
- 中移4G模块-ML302-OpenCpu开发-(MQTT连接阿里云-订阅主题)
- C++ STL 一个简单的stack程序
- cmake之系统头文件(六)
- 输入框设置等宽字体_Glyphs 官方教程 | 字体命名
- 嵌入式100题(58):用户空间与内核通信方式有哪些?
- android wear2.0 更新,又一批手表获得Android Wear 2.0更新
- 视频结构化——原子能力解析
- oracle stdevp函数,plsql和tsql常用函数比对
- 上课为什么要认真听见?