{"id":20172,"date":"2014-01-03T10:00:42","date_gmt":"2014-01-03T08:00:42","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=20172"},"modified":"2014-01-02T17:37:02","modified_gmt":"2014-01-02T15:37:02","slug":"project-student-persistence-with-spring-data","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html","title":{"rendered":"Project Student: Persistence With Spring Data"},"content":{"rendered":"<p>This is part of <a href=\"http:\/\/invariantproperties.com\/2013\/12\/10\/project-student\/\">Project Student<\/a>. Other posts are <a href=\"http:\/\/www.javacodegeeks.com\/2014\/01\/project-student-webservice-server-with-jersey.html\">Webservice Client With Jersey<\/a>, <a href=\"http:\/\/www.javacodegeeks.com\/2013\/12\/project-student-webservice-client-with-jersey.html\">Webservice Server with Jersey<\/a> and <a href=\"http:\/\/invariantproperties.com\/2013\/12\/19\/project-student-business-layer\/\">Business Layer<\/a>.<\/p>\n<p>The final layer of the RESTful webapp onion is the persistence layer.<\/p>\n<p>There are two philosophies for persistence layers. One camp sees the database as a simple store and wants to keep this layer extremely thin. The other camp knows it\u2019s often much faster to perform tasks in the database than to hit the database for the data, do the necessary work in java, and possibly hit the database a second time with the results. This camp often wants a fairly thick persistence layer.<\/p>\n<p>The second camp also has a group of exiles that wants to use stored procedures extensively. This makes the database much more powerful but at the cost of a bit of additional complexity in the persistence layer. It has a major drawback in that stored procedures are database-specific.<\/p>\n<p>A second group of exiles just uses stored procedures for security. I\u2019ve discussed this earlier, e.g., the idea that you should call a stored procedure with username and password and get an \u201caccept\u201d or \u201cdeny\u201d response instead of retrieving the hashed password and doing the comparison in the application. The first approach allows you to use the database\u2019s GRANT and REVOKE privileges to store hashed passwords in a table that\u2019s inaccessible even if an attacker can perform arbitrary SQL injection as the application user.<\/p>\n<p>(Sidenote: you can often write your stored procedures in Java! Oracle supports it, PostgreSQL supports it (via PL\/Java extension), H2 supports it (via the classpath). I don\u2019t know if MySQL supports it. This approach has definite costs but it may be the best solution for many problems.)<\/p>\n<p>Anyway this project only supports CRUD operations at the moment and they\u2019re a classic example of using a thin persistence layer. It\u2019s easy to add \u2018thick\u2019 methods though \u2013 simply create a CourseRepositoryImpl class with them. (This class should NOT implement the CourseRepository interface!)<\/p>\n<h2>Design Decisions<\/h2>\n<p><strong>Spring Data<\/strong> \u2013 we\u2019re using Spring Data because it autogenerates the persistence layer classes.<\/p>\n<h2>Limitations<\/h2>\n<p><strong>Pagination<\/strong> \u2013 there is no attempt to support pagination. This isn\u2019t a big issue since Spring Data already supports it \u2013 we only need to write the glue.<\/p>\n<h2>Configuration<\/h2>\n<p>The basic configuration only requires the <em>@EnableJpaRepositories<\/em> annotation.<\/p>\n<p>The integration test using a pure in-memory embedded database requires a bit more work. Using the Spring embedded database directly doesn\u2019t work even if you use the H2 url that tells it to leave the database server up. The database is properly initialized but then closed before the tests actually run. The result is failures since the database schema is missing.<\/p>\n<p>It would be trivial to use an in-memory database backed by a file but that could cause problems with concurrent runs, accidently pulling in old test data, etc. The obvious solution is using a random temporary backing file but that approach introduces its own problems.<\/p>\n<p>The approach below is to cache the embedded database in the configuration class and only destroy it as the app shuts down. This introduces some non-obvious behavior that forces us to explicitly create a few additional beans as well.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>(IIRC if you create the embedded database in a configuration class and the transaction beans in a configuration file then spring was creating a phantom datasource in the configuration file and initialization failed. This problem went away when I started to create the transaction beans in the same place as the datasource.)<\/p>\n<pre class=\"brush: java; wrap-lines: false\">@Configuration\r\n@EnableJpaRepositories(basePackages = { \"com.invariantproperties.sandbox.student.repository\" })\r\n@EnableTransactionManagement\r\n@PropertySource(\"classpath:test-application.properties\")\r\n@ImportResource(\"classpath:applicationContext-dao.xml\")\r\npublic class TestPersistenceJpaConfig implements DisposableBean {\r\n    private static final Logger log = LoggerFactory.getLogger(TestPersistenceJpaConfig.class);\r\n\r\n    private static final String PROPERTY_NAME_HIBERNATE_DIALECT = \"hibernate.dialect\";\r\n    private static final String PROPERTY_NAME_HIBERNATE_FORMAT_SQL = \"hibernate.format_sql\";\r\n    private static final String PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY = \"hibernate.ejb.naming_strategy\";\r\n    private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = \"hibernate.show_sql\";\r\n    private static final String PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO = \"hibernate.hbm2ddl.auto\";\r\n    private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = \"entitymanager.packages.to.scan\";\r\n    \/\/ private static final String PROPERTY_NAME_PERSISTENCE_UNIT_NAME =\r\n    \/\/ \"persistence.unit.name\";\r\n\r\n    @Resource\r\n    private Environment environment;\r\n\r\n    private EmbeddedDatabase db = null;\r\n\r\n    @Bean\r\n    public DataSource dataSource() {\r\n        final EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();\r\n        db = builder.setType(EmbeddedDatabaseType.H2).build(); \/\/ .script(\"foo.sql\")\r\n        return db;\r\n    }\r\n\r\n    @Bean\r\n    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws ClassNotFoundException {\r\n        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();\r\n\r\n        bean.setDataSource(dataSource());\r\n        bean.setPackagesToScan(environment.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));\r\n        bean.setPersistenceProviderClass(HibernatePersistence.class);\r\n        \/\/ bean.setPersistenceUnitName(environment\r\n        \/\/ .getRequiredProperty(PROPERTY_NAME_PERSISTENCE_UNIT_NAME));\r\n\r\n        HibernateJpaVendorAdapter va = new HibernateJpaVendorAdapter();\r\n        bean.setJpaVendorAdapter(va);\r\n\r\n        Properties jpaProperties = new Properties();\r\n        jpaProperties.put(PROPERTY_NAME_HIBERNATE_DIALECT,\r\nenvironment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));\r\n        jpaProperties.put(PROPERTY_NAME_HIBERNATE_FORMAT_SQL,\r\n                environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_FORMAT_SQL));\r\n        jpaProperties.put(PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY,\r\n                environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_NAMING_STRATEGY));\r\n        jpaProperties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL,\r\n                environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));\r\n        jpaProperties.put(PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO,\r\n                environment.getRequiredProperty(PROPERTY_NAME_HIBERNATE_HBM2DDL_AUTO));\r\n\r\n        bean.setJpaProperties(jpaProperties);\r\n\r\n        return bean;\r\n    }\r\n\r\n    @Bean\r\n    public PlatformTransactionManager transactionManager() {\r\n        JpaTransactionManager tm = new JpaTransactionManager();\r\n\r\n        try {\r\n            tm.setEntityManagerFactory(this.entityManagerFactory().getObject());\r\n        } catch (ClassNotFoundException e) {\r\n            \/\/ TODO: log.\r\n        }\r\n\r\n        return tm;\r\n    }\r\n\r\n    @Bean\r\n    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {\r\n        return new PersistenceExceptionTranslationPostProcessor();\r\n    }\r\n\r\n    @Override\r\n    public void destroy() {\r\n        if (db != null) {\r\n            db.shutdown();\r\n        }\r\n    }\r\n}<\/pre>\n<p>The applicationContext.xml file is empty. The properties file is:<\/p>\n<pre class=\" brush:java\"># hibernate configuration\r\nhibernate.dialect=org.hibernate.dialect.H2Dialect\r\nhibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy\r\nhibernate.show_sql=false\r\nhibernate.format_sql=true\r\nhibernate.hbm2ddl.auto=create\r\n\r\n# jpa configuration\r\nentitymanager.packages.to.scan=com.invariantproperties.sandbox.student.domain\r\npersistence.unit.dataSource=java:comp\/env\/jdbc\/ssDS\r\npersistence.unit.name=ssPU<\/pre>\n<h2>Unit Testing<\/h2>\n<p>There are no unit tests since all of the code is autogenerated. This will change as custom methods are added.<\/p>\n<h2>Integration Testing<\/h2>\n<p>We can now write the integration tests for the business layer:<\/p>\n<pre class=\" brush:java\">@RunWith(SpringJUnit4ClassRunner.class)\r\n@ContextConfiguration(classes = { BusinessApplicationContext.class, TestBusinessApplicationContext.class,\r\n        TestPersistenceJpaConfig.class })\r\n@Transactional\r\n@TransactionConfiguration(defaultRollback = true)\r\npublic class CourseServiceIntegrationTest {\r\n\r\n    @Resource\r\n    private CourseService dao;\r\n\r\n    @Test\r\n    public void testCourseLifecycle() throws Exception {\r\n        final String name = \"Calculus 101\";\r\n\r\n        final Course expected = new Course();\r\n        expected.setName(name);\r\n\r\n        assertNull(expected.getId());\r\n\r\n        \/\/ create course\r\n        Course actual = dao.createCourse(name);\r\n        expected.setId(actual.getId());\r\n        expected.setUuid(actual.getUuid());\r\n        expected.setCreationDate(actual.getCreationDate());\r\n\r\n        assertThat(expected, equalTo(actual));\r\n        assertNotNull(actual.getUuid());\r\n        assertNotNull(actual.getCreationDate());\r\n\r\n        \/\/ get course by id\r\n        actual = dao.findCourseById(expected.getId());\r\n        assertThat(expected, equalTo(actual));\r\n\r\n        \/\/ get course by uuid\r\n        actual = dao.findCourseByUuid(expected.getUuid());\r\n        assertThat(expected, equalTo(actual));\r\n\r\n        \/\/ update course\r\n        expected.setName(\"Calculus 102\");\r\n        actual = dao.updateCourse(actual, expected.getName());\r\n        assertThat(expected, equalTo(actual));\r\n\r\n        \/\/ delete Course\r\n        dao.deleteCourse(expected.getUuid());\r\n        try {\r\n            dao.findCourseByUuid(expected.getUuid());\r\n            fail(\"exception expected\");\r\n        } catch (ObjectNotFoundException e) {\r\n            \/\/ expected\r\n        }\r\n    }\r\n\r\n    \/**\r\n     * @test findCourseById() with unknown course.\r\n     *\/\r\n    @Test(expected = ObjectNotFoundException.class)\r\n    public void testfindCourseByIdWhenCourseIsNotKnown() {\r\n        final Integer id = 1;\r\n        dao.findCourseById(id);\r\n    }\r\n\r\n    \/**\r\n     * @test findCourseByUuid() with unknown Course.\r\n     *\/\r\n    @Test(expected = ObjectNotFoundException.class)\r\n    public void testfindCourseByUuidWhenCourseIsNotKnown() {\r\n        final String uuid = \"missing\";\r\n        dao.findCourseByUuid(uuid);\r\n    }\r\n\r\n    \/**\r\n     * Test updateCourse() with unknown course.\r\n     * \r\n     * @throws ObjectNotFoundException\r\n     *\/\r\n    @Test(expected = ObjectNotFoundException.class)\r\n    public void testUpdateCourseWhenCourseIsNotFound() {\r\n        final Course course = new Course();\r\n        course.setUuid(\"missing\");\r\n        dao.updateCourse(course, \"Calculus 102\");\r\n    }\r\n\r\n    \/**\r\n     * Test deleteCourse() with unknown course.\r\n     * \r\n     * @throws ObjectNotFoundException\r\n     *\/\r\n    @Test(expected = ObjectNotFoundException.class)\r\n    public void testDeleteCourseWhenCourseIsNotFound() {\r\n        dao.deleteCourse(\"missing\");\r\n    }\r\n}<\/pre>\n<h2>Source Code<\/h2>\n<ul>\n<li>The source code is available at <a href=\"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-business<\/a> and <a href=\"http:\/\/code.google.com\/p\/invariant-properties-blog\/source\/browse\/student\/student-persistence\">http:\/\/code.google.com\/p\/invariant-properties-blog\/source\/browse\/student\/student-persistence<\/a>.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<div style=\"border: 1px solid #D8D8D8; background: #FAFAFA; width: 100%; padding-left: 5px;\"><b><i>Reference: <\/i><\/b><a href=\"http:\/\/invariantproperties.com\/2013\/12\/19\/project-student-persistence-with-spring-data\/\">Project Student: Persistence With Spring Data<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\">JCG partner<\/a> Bear Giles at the <a href=\"http:\/\/invariantproperties.com\/\">Invariant Properties<\/a> blog.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This is part of Project Student. Other posts are Webservice Client With Jersey, Webservice Server with Jersey and Business Layer. The final layer of the RESTful webapp onion is the persistence layer. There are two philosophies for persistence layers. One camp sees the database as a simple store and wants to keep this layer extremely &hellip;<\/p>\n","protected":false},"author":113,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30,321],"class_list":["post-20172","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring","tag-spring-data"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Project Student: Persistence With Spring Data<\/title>\n<meta name=\"description\" content=\"This is part of Project Student. Other posts are Webservice Client With Jersey, Webservice Server with Jersey and Business Layer. The final layer of the\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Project Student: Persistence With Spring Data\" \/>\n<meta property=\"og:description\" content=\"This is part of Project Student. Other posts are Webservice Client With Jersey, Webservice Server with Jersey and Business Layer. The final layer of the\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2014-01-03T08:00:42+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Bear Giles\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Bear Giles\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html\"},\"author\":{\"name\":\"Bear Giles\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/91196fd6369bac9f4ec7217ffbca53f9\"},\"headline\":\"Project Student: Persistence With Spring Data\",\"datePublished\":\"2014-01-03T08:00:42+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html\"},\"wordCount\":685,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Spring\",\"Spring Data\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html\",\"name\":\"Project Student: Persistence With Spring Data\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2014-01-03T08:00:42+00:00\",\"description\":\"This is part of Project Student. Other posts are Webservice Client With Jersey, Webservice Server with Jersey and Business Layer. The final layer of the\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/01\\\/project-student-persistence-with-spring-data.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Project Student: Persistence With Spring Data\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/91196fd6369bac9f4ec7217ffbca53f9\",\"name\":\"Bear Giles\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c4e8f47b520b4147cb7f173f9d78cf8862974fdeeff4baea9d6a632cf7b1b54c?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c4e8f47b520b4147cb7f173f9d78cf8862974fdeeff4baea9d6a632cf7b1b54c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/c4e8f47b520b4147cb7f173f9d78cf8862974fdeeff4baea9d6a632cf7b1b54c?s=96&d=mm&r=g\",\"caption\":\"Bear Giles\"},\"sameAs\":[\"http:\\\/\\\/invariantproperties.com\\\/\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/Bear-Giles\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Project Student: Persistence With Spring Data","description":"This is part of Project Student. Other posts are Webservice Client With Jersey, Webservice Server with Jersey and Business Layer. The final layer of the","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html","og_locale":"en_US","og_type":"article","og_title":"Project Student: Persistence With Spring Data","og_description":"This is part of Project Student. Other posts are Webservice Client With Jersey, Webservice Server with Jersey and Business Layer. The final layer of the","og_url":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2014-01-03T08:00:42+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Bear Giles","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Bear Giles","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html"},"author":{"name":"Bear Giles","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/91196fd6369bac9f4ec7217ffbca53f9"},"headline":"Project Student: Persistence With Spring Data","datePublished":"2014-01-03T08:00:42+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html"},"wordCount":685,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Spring","Spring Data"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html","url":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html","name":"Project Student: Persistence With Spring Data","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2014-01-03T08:00:42+00:00","description":"This is part of Project Student. Other posts are Webservice Client With Jersey, Webservice Server with Jersey and Business Layer. The final layer of the","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2014\/01\/project-student-persistence-with-spring-data.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Project Student: Persistence With Spring Data"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/91196fd6369bac9f4ec7217ffbca53f9","name":"Bear Giles","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/c4e8f47b520b4147cb7f173f9d78cf8862974fdeeff4baea9d6a632cf7b1b54c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/c4e8f47b520b4147cb7f173f9d78cf8862974fdeeff4baea9d6a632cf7b1b54c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c4e8f47b520b4147cb7f173f9d78cf8862974fdeeff4baea9d6a632cf7b1b54c?s=96&d=mm&r=g","caption":"Bear Giles"},"sameAs":["http:\/\/invariantproperties.com\/"],"url":"https:\/\/www.javacodegeeks.com\/author\/Bear-Giles"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/20172","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/113"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=20172"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/20172\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=20172"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=20172"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=20172"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}