本文将介绍如何在Spring Boot 工程中添加JPA作为持久化方式。
修改 pom.xml 依赖
与上一篇介绍的 jdbc 不同的是 spring-boot-starter-jdbc 修改为 spring-boot-starter-data-jpa 即可,当然数据库驱动包也是不可少的,如下:
<!-- MYSQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- Spring Boot JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
注意:如果你想JDBC和JPA可以一起使用,Spring Boot 是支持的,你只需要把JDBC和JPA的依赖都添加在pom.xml 中即可。无需其他特殊处理,有关JDBC的使用介绍请看上一篇 “Spring-Boot JDBC 连接数据库”。
修改属性配置文件
在属性配置文件中添加 JPA 相关属性,注意这些并非必须,我们如果只添加dataSource 的 url\username\password\driver-class-name 也可以正常使用,有关JPA的其他配置都是可选的。
spring.jpa.database=
spring.jpa.show-sql=
spring.jpa.properties=
spring.jpa.generate-ddl=
spring.jpa.open-in-view=
spring.jpa.database-platform=
spring.jpa.hibernate.ddl-auto=
spring.data.jpa.repositories.enabled=
spring.jpa.hibernate.naming-strategy=
熟悉JPA的根据名字应基本知道这些分别的作用了。
传统上,JPA实体类在persistence.xml文件中指定的。使用Spring Boot,这个文件是没有必要的,因为它使用“实体扫描”,默认情况下主配置 @EnableAutoConfiguration 或 @SpringBootApplication 下面的所有包都将会被扫描。任何使用注解 @Entity, @Embeddable 或 @MappedSuperclass 的类都将被管理。
Java代码实例
- 一个接口
- 一个Controller
我们创建一个接口 IScoreDao.java ,然后我们继承框架为我们提供好的接口 Repository 或 CrudRepository (CrudRepository 继承自 Repository),其中为我们提供了对数据库的基本操作方法。
package org.springboot.sample.dao;
import java.util.List;
import javax.transaction.Transactional;
import org.springboot.sample.entity.Score;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
public interface IScoreDao extends CrudRepository<Score, Integer> {
@Transactional
@Modifying
@Query("update Score t set t.score = :score where t.id = :id")
int updateScoreById(@Param("score") float score, @Param("id") int id);
@Query("select t from Score t ")
List<Score> getList();
}
注意,如果你其中使用了修改、新增、删除操作,则必须要在接口上面或者对应的方法上面添加 @Transactional 注解,否则会抛出异常。
实体类 Score.java
package org.springboot.sample.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* 成绩
*
* @author 单红宇(365384722)
* @myblog http://blog.csdn.net/catoop/
* @create 2016年1月12日
*/
@Entity
@Table(name = "score")
public class Score implements Serializable {
private static final long serialVersionUID = 8127035730921338189L;
@Id
@GeneratedValue
private int id;
@Column(nullable = false, name="STUDENTID") // 这里说一下,我使用指定数据库列的时候,使用小写会不起作用,修改为大写便正常了。不知道为何,如果遇到一样问题的可以尝试下。
private int stuId;
@Column(nullable = false, name="SUBJECTNAME")
private String subjectName;
@Column(nullable = false)
private float score;
@Column(nullable = false, name="EXAMTIME")
private Date examTime;
// 省去get、set 方法(占用文章空间)
}
ScoreController.java
package org.springboot.sample.controller;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springboot.sample.dao.IScoreDao;
import org.springboot.sample.entity.Score;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/score")
public class ScoreController {
private static final Logger logger = LoggerFactory.getLogger(ScoreController.class);
@Autowired
private IScoreDao scoreService;
@RequestMapping("/scoreList")
public List<Score> getScoreList(){
logger.info("从数据库读取Score集合");
// 测试更新数据库
logger.info("更新的行数:" + scoreService.updateScoreById(88.8f, 2));
scoreService.delete(23);
return scoreService.getList();
}
}
然后在浏览器访问地址:http://localhost:8080/myspringboot/score/scoreList 测试。
最后要说明的是,Spring 会自动为我们继承CrudRepository接口的接口创建实现类。我们只需要在使用的时候直接使用注解 @Autowired 注入即可(IScoreDao 接口上也没有必要增加 @Component 、 @Repository 等注解)。
还有,我这里为了简单起见,直接将操作数据库的在Controller中使用,实际项目中,是不建议这样做的,IScoreDao 的所属角色是数据库持久,我们还应当有 Service(如ScoreService) 来调用 IScoreDao 的方法,然后在Controller 中调用 Service 中的方法。原因是因为,我们数据库访问层,都是接口定义方法,上面注解注入SQL和参数,没有具体的代码逻辑处理。如果我们想在执行SQL之前或之后执行逻辑处理,只能在 Service 中或者Controller(不建议)中。
我们严格按照这种方式去做(持久层只与SQL有关,通过接口定义无逻辑处理),这样才是彻彻底底的持久层。越严格的规范制度,在某种程度上来说其实越有利于代码的管理和项目代码的迭代发展。
当然,如果你实在想要实现自己的 class 实现类,下面会附上一个实例代码,在此之前,我们先看一个图片:
这个图是Spring 使用动态代理创建的接口实例,可以看出,其使用的是 SimpleJpaRepository 类,所以如果我们实现自己的 Repository ,可以扩展 SimpleJpaRepository 并 实现自己的 factory-class 入手,这里不做详解。注意凡事实现 Repository 接口的实现类都不需要添加 @Repository 注解,否则你会遇到问题。
本文介绍JPA 相比上一篇关于JDBC 的介绍增加的文件工程截图为:
熟悉其中一种持久数据的方法后,其他类似的都大同小异。