JPA(Java Persistence API)是Sun官方提出的Java持久化规范。它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据。他的出现主要是为了简化现有的持久化开发工作和整合ORM技术
Spring Data JPA 是 Spring 基于 ORM 框架、JPA 规范的基础上封装的一套JPA应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data JPA 可以极大提高开发效率!
首先,为了连接数据库需要引入jdbc支持,在pom.xml中引入如下配置
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency>
嵌入式数据库通常用于开发和测试环境。Spring-Boot提供自动配置的嵌入式数据库有H2、HSQL、Derby,你不需要提供任何连接配置就能使用。
如h2的依赖
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency>
在 src/main/resources/application.properties
中配置数据源信息
spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver
Spring的JdbcTemplate是自动配置的,你可以直接使用@Autowired来注入到你自己的bean中来使用。
@Service public class DemoSerivce { @Autowired private JdbcTemplate jdbcTemplate; public void create(String name, Integer age) { jdbcTemplate.update("insert into DEMO(NAME, AGE) values(?, ?)", name, age); } public void deleteByName(String name) { jdbcTemplate.update("delete from DEMOwhere NAME = ?", name); } public Integer getAllDemo() { return jdbcTemplate.queryForObject("select count(1) from DEMO", Integer.class); } public void deleteAllDemo() { jdbcTemplate.update("delete from DEMO"); } }
测试用例要增加依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
测试代码
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(Main.class) public class ApplicationTests { @Autowired private DemoSerivce demoSerivce; @Before public void setUp() { // 准备,清空表 demoSerivce.deleteAllDemo(); } @Test public void test() throws Exception { // 插入5个 demoSerivce.create("a", 1); demoSerivce.create("b", 2); demoSerivce.create("c", 3); demoSerivce.create("d", 4); demoSerivce.create("e", 5); Assert.assertEquals(5, demoSerivce.getAllDemo().intValue()); demoSerivce.deleteByName("a"); demoSerivce.deleteByName("e"); // 查数据库,应该有5个 Assert.assertEquals(3, demoSerivce.getAllDemo().intValue()); } }
为了解决这些大量枯燥的数据操作语句,我们第一个想到的是使用ORM框架,比如:Hibernate。通过整合Hibernate之后,我们以操作Java实体的方式最终将数据改变映射到数据库表中。
为了解决抽象各个Java实体基本的“增删改查”操作,我们通常会以泛型的方式封装一个模板Dao来进行抽象简化,但是这样依然不是很方便,我们需要针对每个实体编写一个继承自泛型模板Dao的接口,再编写该接口的实现。虽然一些基础的数据访问已经可以得到很好的复用,但是在代码结构上针对每个实体都会有一堆Dao的接口和实现。
由于模板Dao的实现,使得这些具体实体的Dao层已经变的非常“薄”,有一些具体实体的Dao实现可能完全就是对模板Dao的简单代理,并且往往这样的实现类可能会出现在很多实体上。Spring-data-jpa的出现正可以让这样一个已经很“薄”的数据访问层变成只是一层接口的编写方式。
<dependency <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
在 src/main/resources/application.properties
中配置数据源信息
spring.datasource.url=jdbc:mysql://localhost:3306/test spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.jpa.properties.hibernate.hbm2ddl.auto=update
spring.jpa.properties.hibernate.hbm2ddl.auto是hibernate的配置属性,其主要作用是:自动创建、更新、验证数据库表结构。该参数的几种配置如下
@Entity public class DemoEntity { @Id @GeneratedValue private long id; private String title; private String content; public DemoEntity() { } public DemoEntity(String title, String content) { this.title = title; this.content = content; } // get set 略 }
public interface DemoRepository extends JpaRepository<DemoEntity, Long> { DemoEntity findByTitle(String title); DemoEntity findByTitleAndContent(String title, String content); // @Query("select u from DemoEntity u where u.content=:content") @Query("from DemoEntity u where u.content=:content") DemoEntity sqlFind(@Param("content") String content); }
sql中不要写表名,要写实体名,他会自动转化为表名的。
上面 findByTitle(String title)
与 findByTitleAndContent(String title, String content)
,没有写sql,但框架会自动按名字对上面的方对创建sql。
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(Main.class) public class UnitTest { @Autowired DemoRepository demoRepository; @Test public void test() { for(int i=0;i<10;i++) { demoRepository.save(new DemoEntity("title"+i, "content"+i)); } Assert.assertEquals(10, demoRepository.findAll().size()); } @Test public void testfindbytitle() { DemoEntity res = demoRepository.findByTitle("title8"); Assert.assertEquals("title8", res.getTitle()); } @Test public void testfindbytitleandcontent() { DemoEntity res = demoRepository.findByTitleAndContent("title9", "content9"); Assert.assertEquals("title9", res.getTitle()); Assert.assertEquals("content9", res.getContent()); } @Test public void testsqlFind() { DemoEntity res = demoRepository.sqlFind("content7"); Assert.assertEquals("content7", res.getContent()); } }