diff --git a/spring-boot-samples/pom.xml b/spring-boot-samples/pom.xml index d5b6acda5b..16c5c4e79e 100644 --- a/spring-boot-samples/pom.xml +++ b/spring-boot-samples/pom.xml @@ -44,6 +44,7 @@ spring-boot-sample-jetty-ssl spring-boot-sample-jetty8 spring-boot-sample-jetty8-ssl + spring-boot-sample-jpa spring-boot-sample-jta-atomikos spring-boot-sample-jta-bitronix spring-boot-sample-jta-jndi diff --git a/spring-boot-samples/spring-boot-sample-jpa/pom.xml b/spring-boot-samples/spring-boot-sample-jpa/pom.xml new file mode 100644 index 0000000000..76195c85ff --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-samples + 1.2.0.BUILD-SNAPSHOT + + spring-boot-sample-jpa + Spring Boot JPA Sample + Spring Boot JPA Sample + http://projects.spring.io/spring-boot/ + + Pivotal Software, Inc. + http://www.spring.io + + + ${basedir}/../.. + + + + org.springframework.boot + spring-boot-starter-freemarker + + + org.hibernate + hibernate-entitymanager + + + org.hsqldb + hsqldb + runtime + + + org.springframework + spring-orm + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/SampleJpaApplication.java b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/SampleJpaApplication.java new file mode 100644 index 0000000000..9f1855247d --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/SampleJpaApplication.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.jpa; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SampleJpaApplication { + + public static void main(String[] args) throws Exception { + SpringApplication.run(SampleJpaApplication.class, args); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/domain/Note.java b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/domain/Note.java new file mode 100644 index 0000000000..9a2442c3c2 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/domain/Note.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.jpa.domain; + +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToMany; + +@Entity +public class Note { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String title; + + private String body; + + @ManyToMany + private List tags; + + public long getId() { + return this.id; + } + + public void setId(long id) { + this.id = id; + } + + public String getTitle() { + return this.title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getBody() { + return this.body; + } + + public void setBody(String body) { + this.body = body; + } + + public List getTags() { + return this.tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + +} diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/domain/Tag.java b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/domain/Tag.java new file mode 100644 index 0000000000..4d8bfc09d1 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/domain/Tag.java @@ -0,0 +1,63 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.jpa.domain; + +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToMany; + +@Entity +public class Tag { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private long id; + + private String name; + + @ManyToMany(mappedBy = "tags") + private List notes; + + public long getId() { + return this.id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public List getNotes() { + return this.notes; + } + + public void setNotes(List notes) { + this.notes = notes; + } + +} diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/JpaNoteRepository.java b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/JpaNoteRepository.java new file mode 100644 index 0000000000..0bd11447a0 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/JpaNoteRepository.java @@ -0,0 +1,40 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.jpa.repository; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.springframework.stereotype.Repository; + +import sample.jpa.domain.Note; + +@Repository +class JpaNoteRepository implements NoteRepository { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public List findAll() { + return this.entityManager.createQuery("SELECT n FROM Note n", Note.class) + .getResultList(); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/JpaTagRepository.java b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/JpaTagRepository.java new file mode 100644 index 0000000000..7322c42cab --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/JpaTagRepository.java @@ -0,0 +1,40 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.jpa.repository; + +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.springframework.stereotype.Repository; + +import sample.jpa.domain.Tag; + +@Repository +class JpaTagRepository implements TagRepository { + + @PersistenceContext + private EntityManager entityManager; + + @Override + public List findAll() { + return this.entityManager.createQuery("SELECT t FROM Tag t", Tag.class) + .getResultList(); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/NoteRepository.java b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/NoteRepository.java new file mode 100644 index 0000000000..b27af92e3c --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/NoteRepository.java @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.jpa.repository; + +import java.util.List; + +import sample.jpa.domain.Note; + +public interface NoteRepository { + + List findAll(); + +} diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/TagRepository.java b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/TagRepository.java new file mode 100644 index 0000000000..897ef7f08f --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/repository/TagRepository.java @@ -0,0 +1,27 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.jpa.repository; + +import java.util.List; + +import sample.jpa.domain.Tag; + +public interface TagRepository { + + List findAll(); + +} diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/web/IndexController.java b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/web/IndexController.java new file mode 100644 index 0000000000..61a0f80afe --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/main/java/sample/jpa/web/IndexController.java @@ -0,0 +1,45 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.jpa.web; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +import sample.jpa.domain.Note; +import sample.jpa.repository.NoteRepository; + +@Controller +public class IndexController { + + @Autowired + private NoteRepository noteRepository; + + @RequestMapping("/") + @Transactional(readOnly = true) + public ModelAndView index() { + List notes = this.noteRepository.findAll(); + ModelAndView modelAndView = new ModelAndView("index"); + modelAndView.addObject("notes", notes); + return modelAndView; + } + +} diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/main/resources/import.sql b/spring-boot-samples/spring-boot-sample-jpa/src/main/resources/import.sql new file mode 100644 index 0000000000..a3d2222035 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/main/resources/import.sql @@ -0,0 +1,17 @@ +insert into tag(name) values ('Spring projects') +insert into tag(name) values ('Apache projects') +insert into tag(name) values ('Open source') + +insert into note(title, body) values ('Spring Boot', 'Takes an opinionated view of building production-ready Spring applications.') +insert into note(title, body) values ('Spring Framework', 'Core support for dependency injection, transaction management, web applications, data access, messaging, testing and more.') +insert into note(title, body) values ('Spring Integration', 'Extends the Spring programming model to support the well-known Enterprise Integration Patterns.') +insert into note(title, body) values ('Tomcat', 'Apache Tomcat is an open source software implementation of the Java Servlet and JavaServer Pages technologies.') + +insert into note_tags(notes_id, tags_id) values (1, 1) +insert into note_tags(notes_id, tags_id) values (2, 1) +insert into note_tags(notes_id, tags_id) values (3, 1) +insert into note_tags(notes_id, tags_id) values (1, 3) +insert into note_tags(notes_id, tags_id) values (2, 3) +insert into note_tags(notes_id, tags_id) values (3, 3) +insert into note_tags(notes_id, tags_id) values (4, 2) +insert into note_tags(notes_id, tags_id) values (4, 3) \ No newline at end of file diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/main/resources/templates/index.ftl b/spring-boot-samples/spring-boot-sample-jpa/src/main/resources/templates/index.ftl new file mode 100644 index 0000000000..100e1b660e --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/main/resources/templates/index.ftl @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + +<#list notes as note> + + + + + + + +
TitleBodyTags
${note.title}${note.body} +<#list note.tags as tag> + ${tag.name} + +
+ + + diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/test/java/sample/jpa/SampleJpaApplicationTests.java b/spring-boot-samples/spring-boot-sample-jpa/src/test/java/sample/jpa/SampleJpaApplicationTests.java new file mode 100644 index 0000000000..1f14e18c21 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/test/java/sample/jpa/SampleJpaApplicationTests.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package sample.jpa; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.xpath; + +/** + * Integration test to run the application. + * + * @author Oliver Gierke + * @author Dave Syer + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SampleJpaApplication.class) +@WebAppConfiguration +public class SampleJpaApplicationTests { + + @Autowired + private WebApplicationContext context; + + private MockMvc mvc; + + @Before + public void setUp() { + this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build(); + } + + @Test + public void testHome() throws Exception { + this.mvc.perform(get("/")).andExpect(status().isOk()) + .andExpect(xpath("//tbody/tr").nodeCount(4)); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/test/java/sample/jpa/repository/JpaNoteRepositoryIntegrationTests.java b/spring-boot-samples/spring-boot-sample-jpa/src/test/java/sample/jpa/repository/JpaNoteRepositoryIntegrationTests.java new file mode 100644 index 0000000000..d8a5237f12 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/test/java/sample/jpa/repository/JpaNoteRepositoryIntegrationTests.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package sample.jpa.repository; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import sample.jpa.SampleJpaApplication; +import sample.jpa.domain.Note; + +import static org.junit.Assert.assertEquals; + +/** + * Integration tests for {@link JpaNoteRepository}. + * + * @author Andy Wilkinson + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SampleJpaApplication.class) +public class JpaNoteRepositoryIntegrationTests { + + @Autowired + JpaNoteRepository repository; + + @Test + public void findsAllNotes() { + List notes = this.repository.findAll(); + assertEquals(4, notes.size()); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-jpa/src/test/java/sample/jpa/repository/JpaTagRepositoryIntegrationTests.java b/spring-boot-samples/spring-boot-sample-jpa/src/test/java/sample/jpa/repository/JpaTagRepositoryIntegrationTests.java new file mode 100644 index 0000000000..add24b39d0 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-jpa/src/test/java/sample/jpa/repository/JpaTagRepositoryIntegrationTests.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package sample.jpa.repository; + +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import sample.jpa.SampleJpaApplication; +import sample.jpa.domain.Tag; + +import static org.junit.Assert.assertEquals; + +/** + * Integration tests for {@link JpaTagRepository}. + * + * @author Andy Wilkinson + */ +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = SampleJpaApplication.class) +public class JpaTagRepositoryIntegrationTests { + + @Autowired + JpaTagRepository repository; + + @Test + public void findsAllTags() { + List tags = this.repository.findAll(); + assertEquals(3, tags.size()); + } + +}