Springboot使用JPA操作数据库
第七章 使用JPA操作数据库
本章主要介绍如何在Spring Boot的Web应用中使用Mysq数据库,也充分展示Spring Boot的优势(尽可能少的代码和配置).
数据访问层我们将使用Spring Data JPA和Hibernate(JPA的实现之一).
Maven pom.xml文件
lightsword/pom.xml
在项目中增加如下依赖文件
org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-data-jpa mysql mysql-connector-java
配置文件application.properties
在src/main/resources/application.properties中设置数据源和jpa配置:
# mysqlspring.datasource.url = jdbc:mysql://localhost:3306/lightsword?useUnicode=true&characterEncoding=UTF8spring.datasource.username = root# root@localhost ::TZaMojg3ntdspring.datasource.password = rootspring.datasource.driverClassName = com.mysql.jdbc.Driverspring.datasource.max-active=0spring.datasource.max-idle=0spring.datasource.min-idle=0spring.datasource.max-wait=10000spring.datasource.max-wait-millis=31536000# Specify the DBMSspring.jpa.database = MYSQL# Show or not log for each sql queryspring.jpa.show-sql = true# Hibernate ddl auto (create, create-drop, update)spring.jpa.hibernate.ddl-auto = update# Naming strategyspring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy# stripped before adding them to the entity manager)spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
全部的配置都在如上的文件中了,不需要另外的XML配置和Java配置。
上文中的数据库配置,你需要换成你的数据库的地址和用户名密码。
hibernate的ddl-auto=update配置表名,数据库的表和列会自动创建(根据Java实体类,在scala中,只要在实体类上标注@Entity,成员变量上标注@BeanProperty),这里 可以看到更多得hibernate配置。
实体类
创建一个HttpApi实体类,实体和Mysql数据库的http_api表相对应(这个表字段会在应用启动的时候,自动生成)。
package com.springboot.in.action.entityimport java.util.Dateimport javax.persistence.{ Entity, GeneratedValue, GenerationType, Id }import scala.language.implicitConversionsimport scala.beans.BeanProperty@Entityclass HttpApi { @Id @GeneratedValue(strategy = GenerationType.AUTO) @BeanProperty var id: Integer = _ @BeanProperty var httpSuiteId: Integer = _ //用例名称 @BeanProperty var name: String = _ //用例状态: -1未执行 0失败 1成功 @BeanProperty var state: Integer = _ //接口 @BeanProperty var url: String = _ //方法GET,POST @BeanProperty var method: String = _ //post参数json string @BeanProperty var paramJsonStr: String = _ //期望输出 @BeanProperty var expectOutput: String = _ //实际输出 @BeanProperty var actualOutput: String = _ @BeanProperty var runTimes: Integer = _ @BeanProperty var owner: String = _ @BeanProperty var gmtCreate: Date = _ @BeanProperty var gmtModify: Date = _}
实体的数据访问层HttpApiDao
实体的数据访问层HttpApiDao非常简单,只需要继承CrudRespositroy即可,CrudRespositroy已经实现了save,delete,deleteAll,findOne和findAll.
(比较神奇的时这些方法其实CrudRespositroy中其实并没有实现,并且通过对dao层的方法的命名还可以实现新的方法).
当然,如果基本的CRUD方法满足不了我们稍微复杂一些的sql查询,我们可以直接定义sql查询语句,绑定dao层的方法.实例在如下代码中可以看到:
package com.springboot.in.action.daoimport java.util.Listimport com.springboot.in.action.entity.HttpApiimport org.springframework.data.jpa.repository.Queryimport org.springframework.data.repository.CrudRepositoryimport scala.language.implicitConversionstrait HttpApiDao extends CrudRepository[HttpApi, Integer] { def findAll(): List[HttpApi] // JavaConversions def save(t: HttpApi): HttpApi def findOne(id: Integer): HttpApi @Query(value = "SELECT * FROM http_api where http_suite_id = ?1", nativeQuery = true) def listByHttpSuiteId(id: Integer): List[HttpApi] @Query(value = "SELECT id FROM http_api where http_suite_id = ?1", nativeQuery = true) def listTestCaseId(httpSuiteId: Integer): List[Integer] // 隐式转换,直接用scala的List会报错:javax.persistence.NonUniqueResultException: result returns more than one elements] with root cause @Query(value = "SELECT * FROM http_api where name like %?1% ", nativeQuery = true) // like '%?%' def findByName(name: String): List[HttpApi] @Query(value = "select count(*) from http_api where http_suite_id = ?1 and state = 1", nativeQuery = true) def countPass(httpSuiteId: Integer): Int @Query(value = "select count(*) from http_api where http_suite_id = ?1 and state = 0", nativeQuery = true) def countFail(httpSuiteId: Integer): Int}
重点看一下
@Query注解里面的value和nativeQuery=true,意思是使用原生的sql查询语句.
sql模糊查询like语法,我们在写sql的时候是这样写的
like '%?%'
但是在@Query的value字符串中, 这样写
SELECT * FROM http_api where name like %?1%
- 在Springboot跟scala集成开发过程中,集合类需要使用java里面的api,直接用scala的List会报错:
javax.persistence.NonUniqueResultException: result returns more than one elements] with root cause.
可以显示声明:
import java.util.List
也可以使用隐式转换:
import scala.collection.JavaConversions._
控制器HttpApiController
新建控制器HttpApiController.scala代码
package com.springboot.in.action.controllerimport java.util.Dateimport java.util.concurrent.CountDownLatchimport com.alibaba.fastjson.JSONimport com.springboot.in.action.dao.{HttpApiDao, HttpReportDao, HttpSuiteDao}import com.springboot.in.action.engine.OkHttpimport com.springboot.in.action.entity.{HttpApi, HttpReport}import org.springframework.beans.factory.annotation.Autowiredimport org.springframework.ui.Modelimport org.springframework.web.bind.annotation.{PathVariable, RequestMapping, RequestMethod, RequestParam, ResponseBody, RestController}import org.springframework.web.servlet.ModelAndViewimport scala.collection.JavaConversions._@RestController@RequestMapping(Array("/httpapi"))class HttpApiController @Autowired() ( val HttpSuiteDao: HttpSuiteDao, val HttpApiDao: HttpApiDao, val HttpReportDao: HttpReportDao) { @RequestMapping(value = { Array("", "/") }, method = Array(RequestMethod.GET)) def list(model: Model) = { model.addAttribute("httpapis", HttpApiDao.findAll()) new ModelAndView("/httpapi/list") } @RequestMapping(value = { Array("/json") }, method = Array(RequestMethod.GET)) def listJson() = HttpApiDao.findAll() @RequestMapping(value = { Array("/listHttpSuiteTestCase") }, method = Array(RequestMethod.GET)) def listHttpSuiteTestCase(model: Model, @RequestParam(value = "httpSuiteId") httpSuiteId: Integer) = { var httpapis = HttpApiDao.listByHttpSuiteId(httpSuiteId) model.addAttribute("httpapis", httpapis) model.addAttribute("httpSuiteId", httpSuiteId) model.addAttribute("httpSuiteName", HttpSuiteDao.findOne(httpSuiteId).name) new ModelAndView("/httpapi/listHttpSuiteTestCase") } @RequestMapping(value = { Array("/listHttpSuiteTestCaseJson") }, method = Array(RequestMethod.GET)) @ResponseBody def listHttpSuiteTestCaseJson(model: Model, @RequestParam(value = "httpSuiteId") httpSuiteId: Integer) = { HttpApiDao.listByHttpSuiteId(httpSuiteId) } @RequestMapping(Array("/newPage/{httpSuiteId}")) def goNewPage(@PathVariable(value = "httpSuiteId") httpSuiteId: Integer, model: Model) = { model.addAttribute("httpSuiteId", httpSuiteId) model.addAttribute("httpSuiteName", HttpSuiteDao.findOne(httpSuiteId).name) new ModelAndView("/httpapi/new") } / * 项目下面的用例编辑 */ @RequestMapping(Array("/editPage/{caseId}")) def goEditPage(model: Model, @PathVariable(value = "caseId") caseId: Integer, @RequestParam(value = "httpSuiteId") httpSuiteId: Integer) = { val httpapi = HttpApiDao.findOne(caseId) model.addAttribute("httpapi", httpapi) model.addAttribute("httpSuiteId", httpSuiteId) model.addAttribute("httpSuiteName", HttpSuiteDao.findOne(httpSuiteId).name) new ModelAndView("/httpapi/edit") } @RequestMapping(Array("/copyPage/{caseId}")) def goCopyPage(model: Model, @PathVariable(value = "caseId") caseId: Integer, @RequestParam(value = "httpSuiteId") httpSuiteId: Integer) = { val httpapi = HttpApiDao.findOne(caseId) model.addAttribute("httpapi", httpapi) model.addAttribute("httpSuiteId", httpSuiteId) model.addAttribute("httpSuiteName", HttpSuiteDao.findOne(httpSuiteId).name) new ModelAndView("/httpapi/copy") } @RequestMapping(Array("/detailPage/{id}")) def goDetailPage(model: Model, @PathVariable(value = "id") id: Integer) = { val httpapi = HttpApiDao.findOne(id) model.addAttribute("httpapi", httpapi) new ModelAndView("/httpapi/detail") } @RequestMapping(value = Array("/postnew"), method = Array(RequestMethod.POST)) @ResponseBody def newOne(@RequestParam(value = "httpSuiteId") httpSuiteId: Integer, @RequestParam(value = "name") name: String, @RequestParam(value = "url") url: String, @RequestParam(value = "method") method: String, @RequestParam(value = "paramJsonStr") paramJsonStr: String, @RequestParam(value = "expectOutput") expectOutput: String, @RequestParam(value = "actualOutput") actualOutput: String, @RequestParam(value = "owner") owner: String) = { val httpapi = new HttpApi() httpapi.httpSuiteId = httpSuiteId httpapi.name = name httpapi.url = url httpapi.method = method httpapi.paramJsonStr = paramJsonStr httpapi.expectOutput = expectOutput httpapi.actualOutput = actualOutput httpapi.runTimes = 0 httpapi.state = -1 httpapi.owner = owner httpapi.gmtCreate = new Date() httpapi.gmtModify = new Date() HttpApiDao.save(httpapi) } @RequestMapping(value = Array("/postedit"), method = Array(RequestMethod.POST)) @ResponseBody def editOne(@RequestParam(value = "id") id: Integer, @RequestParam(value = "name") name: String, @RequestParam(value = "url") url: String, @RequestParam(value = "method") method: String, @RequestParam(value = "paramJsonStr") paramJsonStr: String, @RequestParam(value = "expectOutput") expectOutput: String) = { val httpapi = HttpApiDao.findOne(id) httpapi.name = name httpapi.url = url httpapi.method = method httpapi.paramJsonStr = paramJsonStr httpapi.expectOutput = expectOutput httpapi.gmtModify = new Date() HttpApiDao.save(httpapi) } / * 在新建用例页面,调试用例用 */ @RequestMapping(value = Array("/debugTest"), method = Array(RequestMethod.GET)) @ResponseBody def debugTest(@RequestParam(value = "url") url: String, @RequestParam(value = "method") method: String, @RequestParam(value = "paramJsonStr") paramJsonStr: String) = { OkHttp.run(url, method, paramJsonStr) } / * 执行用例 */ @RequestMapping(value = Array("/runTest"), method = Array(RequestMethod.GET)) @ResponseBody def debugTest(@RequestParam(value = "id") id: Integer) = { runTestCase(id) } / * 回归项目全部用例,每个用例单独起一个线程跑 */ @RequestMapping(value = Array("/testHttpSuite"), method = Array(RequestMethod.GET)) @ResponseBody def testProject(@RequestParam(value = "httpSuiteId") httpSuiteId: Integer) = { val caseIds = HttpApiDao.listTestCaseId(httpSuiteId) val threads = caseIds.size val countDownLatch = new CountDownLatch(threads) for (cid 可以直接运行,可以看到测试结果.也可以浏览器访问:http://localhost:8888/httpapi/listHttpSuiteTestCaseJson?httpSuiteId=1看到Restful接口的json返回:
[{"id":1,"httpSuiteId":1,"name":"HelloSB测试","state":1,"url":"http://localhost:8888/hello","method":"GET","paramJsonStr":"{}","expectOutput":"LightSword","actualOutput":"{\"conent\":\"Hello, LightSword! Now is: Mon Jun 27 13:23:20 CST 2016\"}","runTimes":1,"owner":"陈光剑","gmtCreate":1467004998000,"gmtModify":1467005001000}]
#jpa#
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!