javascript
spring 事务持久性_项目学生:Spring数据的持久性
spring 事務(wù)持久性
這是Project Student的一部分。 其他職位包括帶有Jersey的Webservice Client,帶有Jersey的 Webservice Server和業(yè)務(wù)層 。
RESTful webapp onion的最后一層是持久層。
持久層有兩種哲學(xué)。 一個(gè)陣營(yíng)將數(shù)據(jù)庫(kù)視為一個(gè)簡(jiǎn)單的存儲(chǔ),并希望保持這一層非常薄。 另一陣營(yíng)知道,在數(shù)據(jù)庫(kù)中執(zhí)行任務(wù)通常比訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)中的數(shù)據(jù),用Java完成必要的工作以及可能第二次訪(fǎng)問(wèn)結(jié)果要快得多。 該陣營(yíng)通常需要一個(gè)相當(dāng)厚的持久層。
第二陣營(yíng)也有一群希望廣泛使用存儲(chǔ)過(guò)程的流放者。 這使數(shù)據(jù)庫(kù)功能更加強(qiáng)大,但在持久層中卻付出了一些額外的復(fù)雜性。 它的主要缺點(diǎn)是存儲(chǔ)過(guò)程是特定于數(shù)據(jù)庫(kù)的。
第二批流亡者僅使用存儲(chǔ)過(guò)程來(lái)提高安全性。 我已經(jīng)在前面進(jìn)行了討論,例如,您應(yīng)該使用用戶(hù)名和密碼來(lái)調(diào)用存儲(chǔ)過(guò)程并獲得“接受”或“拒絕”響應(yīng),而不是檢索哈希密碼并在應(yīng)用程序中進(jìn)行比較。 第一種方法允許您使用數(shù)據(jù)庫(kù)的GRANT和REVOKE特權(quán)將哈希密碼存儲(chǔ)在不可訪(fǎng)問(wèn)的表中,即使攻擊者可以以應(yīng)用程序用戶(hù)身份執(zhí)行任意SQL注入。
(旁注:您通常可以用Java編寫(xiě)存儲(chǔ)過(guò)程!Oracle支持它,PostgreSQL支持它(通過(guò)PL / Java擴(kuò)展),H2支持它(通過(guò)類(lèi)路徑)。我不知道MySQL是否支持它。確定的成本,但這可能是解決許多問(wèn)題的最佳解決方案。)
無(wú)論如何,該項(xiàng)目目前僅支持CRUD操作,它們是使用薄型持久層的經(jīng)典示例。 但是,添加“ thick”方法很容易–只需使用它們創(chuàng)建一個(gè)CourseRepositoryImpl類(lèi)。 (此類(lèi)不應(yīng)實(shí)現(xiàn)CourseRepository接口!)
設(shè)計(jì)決策
Spring Data –我們使用Spring Data是因?yàn)樗鼤?huì)自動(dòng)生成持久層類(lèi)。
局限性
分頁(yè) –沒(méi)有嘗試支持分頁(yè)。 由于Spring Data已經(jīng)支持它,所以這不是一個(gè)大問(wèn)題-我們只需要編寫(xiě)膠水即可。
組態(tài)
基本配置僅需要@EnableJpaRepositories批注。
使用純內(nèi)存嵌入式數(shù)據(jù)庫(kù)進(jìn)行集成測(cè)試需要做更多的工作。 即使使用H2 URL告訴它使數(shù)據(jù)庫(kù)服務(wù)器關(guān)閉,直接使用Spring嵌入式數(shù)據(jù)庫(kù)也不起作用。 數(shù)據(jù)庫(kù)已正確初始化,但在測(cè)試實(shí)際運(yùn)行之前已關(guān)閉。 結(jié)果是失敗,因?yàn)槿鄙贁?shù)據(jù)庫(kù)架構(gòu)。
使用由文件支持的內(nèi)存數(shù)據(jù)庫(kù)是微不足道的,但可能導(dǎo)致并發(fā)運(yùn)行問(wèn)題,意外拉入舊的測(cè)試數(shù)據(jù)等。顯而易見(jiàn)的解決方案是使用隨機(jī)的臨時(shí)支持文件,但是這種方法會(huì)帶來(lái)自身的問(wèn)題。 。
下面的方法是將嵌入式數(shù)據(jù)庫(kù)緩存在配置類(lèi)中,并僅在應(yīng)用程序關(guān)閉時(shí)銷(xiāo)毀它。 這引入了一些非顯而易見(jiàn)的行為,迫使我們也必須顯式創(chuàng)建一些其他bean。
(IIRC,如果您在配置類(lèi)中創(chuàng)建嵌入式數(shù)據(jù)庫(kù),并在配置文件中創(chuàng)建事務(wù)Bean,則spring在配置文件中創(chuàng)建幻像數(shù)據(jù)源,并且初始化失敗。當(dāng)我開(kāi)始在同一文件中創(chuàng)建事務(wù)Bean時(shí),此問(wèn)題消失了放置為數(shù)據(jù)源。)
@Configuration @EnableJpaRepositories(basePackages = { "com.invariantproperties.sandbox.student.repository" }) @EnableTransactionManagement @PropertySource("classpath:test-application.properties") @ImportResource("classpath:applicationContext-dao.xml") public class TestPersistenceJpaConfig implements DisposableBean {private static final Logger log = LoggerFactory.getLogger(TestPersistenceJpaConfig.class);private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = "hibernate.format_sql";private static final String PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY = "hibernate.ejb.naming_strategy";private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";private static final String PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO = "hibernate.hbm2ddl.auto";private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";// private static final String PROPERTY_NAME_PERSISTENCE_UNIT_NAME =// "persistence.unit.name";@Resourceprivate Environment environment;private EmbeddedDatabase db = null;@Beanpublic DataSource dataSource() {final EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();db = builder.setType(EmbeddedDatabaseType.H2).build(); // .script("foo.sql")return db;}@Beanpublic LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException {LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();bean.setDataSource(dataSource());bean.setPackagesToScan(environment.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));bean.setPersistenceProviderClass(HibernatePersistence.class);// bean.setPersistenceUnitName(environment// .getRequiredProperty(PROPERTY_NAME_PERSISTENCE_UNIT_NAME));HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();bean.setJpaVendorAdapter(va);Properties jpaProperties = new Properties();jpaProperties.put(PROPERTY_NAME_HIBERNATE_DIALECT, environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));jpaProperties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL,environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));jpaProperties.put(PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY,environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY));jpaProperties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL,environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));jpaProperties.put(PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO,environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO));bean.setJpaProperties(jpaProperties);return bean;}@Beanpublic PlatformTransactionManager transactionManager() {JpaTransactionManager tm = new JpaTransactionManager();try {tm.setEntityManagerFactory(this.entityManagerFactory().getObject());} catch (ClassNotFoundException e) {// TODO: log.}return tm;}@Beanpublic PersistenceExceptionTranslationPostProcessor exceptionTranslation() {return new PersistenceExceptionTranslationPostProcessor();}@Overridepublic void destroy() {if (db != null) {db.shutdown();}} }applicationContext.xml文件為空。 該屬性文件是:
# hibernate configuration hibernate.dialect=org.hibernate.dialect.H2Dialect hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy hibernate.show_sql=false hibernate.format_sql=true hibernate.hbm2ddl.auto=create# jpa configuration entitymanager.packages.to.scan=com.invariantproperties.sandbox.student.domain persistence.unit.dataSource=java:comp/env/jdbc/ssDS persistence.unit.name=ssPU單元測(cè)試
由于所有代碼都是自動(dòng)生成的,因此沒(méi)有單元測(cè)試。 這將隨著添加自定義方法而改變。
整合測(cè)試
現(xiàn)在,我們可以編寫(xiě)業(yè)務(wù)層的集成測(cè)試:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { BusinessApplicationContext.class, TestBusinessApplicationContext.class,TestPersistenceJpaConfig.class }) @Transactional @TransactionConfiguration(defaultRollback = true) public class CourseServiceIntegrationTest {@Resourceprivate CourseService dao;@Testpublic void testCourseLifecycle() throws Exception {final String name = "Calculus 101";final Course expected = new Course();expected.setName(name);assertNull(expected.getId());// create courseCourse actual = dao.createCourse(name);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 = dao.findCourseById(expected.getId());assertThat(expected, equalTo(actual));// get course by uuidactual = dao.findCourseByUuid(expected.getUuid());assertThat(expected, equalTo(actual));// update courseexpected.setName("Calculus 102");actual = dao.updateCourse(actual, expected.getName());assertThat(expected, equalTo(actual));// delete Coursedao.deleteCourse(expected.getUuid());try {dao.findCourseByUuid(expected.getUuid());fail("exception expected");} catch (ObjectNotFoundException e) {// expected}}/*** @test findCourseById() with unknown course.*/@Test(expected = ObjectNotFoundException.class)public void testfindCourseByIdWhenCourseIsNotKnown() {final Integer id = 1;dao.findCourseById(id);}/*** @test findCourseByUuid() with unknown Course.*/@Test(expected = ObjectNotFoundException.class)public void testfindCourseByUuidWhenCourseIsNotKnown() {final String uuid = "missing";dao.findCourseByUuid(uuid);}/*** Test updateCourse() with unknown course.* * @throws ObjectNotFoundException*/@Test(expected = ObjectNotFoundException.class)public void testUpdateCourseWhenCourseIsNotFound() {final Course course = new Course();course.setUuid("missing");dao.updateCourse(course, "Calculus 102");}/*** Test deleteCourse() with unknown course.* * @throws ObjectNotFoundException*/@Test(expected = ObjectNotFoundException.class)public void testDeleteCourseWhenCourseIsNotFound() {dao.deleteCourse("missing");} }源代碼
- 可從http://code.google.com/p/invariant-properties-blog/source/browse/student/student-business和http://code.google.com/p/invariant-properties-獲得源代碼。 blog / source / browse / student / student-persistence 。
翻譯自: https://www.javacodegeeks.com/2014/01/project-student-persistence-with-spring-data.html
spring 事務(wù)持久性
總結(jié)
以上是生活随笔為你收集整理的spring 事务持久性_项目学生:Spring数据的持久性的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: API网关正在经历身份危机
- 下一篇: 业务合同备案在哪查(业务合同备案)