前言:谈起操作数据库,大致可以分为几个阶段:首先是JDBC阶段,初学JDBC可能会使用原生的JDBC的API,再然后可能会使用数据库连接池,比如:C3P0,DBCP,还有一些第三方工具,比如dbutils等,楼主认为JDBC是贯穿始终的,即使到了框架部分,也会对JDBC进行整合,此阶段还是自己手写SQL语句;下一个阶段就是休眠,大家体会到了操作数据库可以不用自己手动编写SQL,调用Hibernate提供的API即可。今天给大家介绍的是操作数据库的另一个模块JPA,即Java持久层的API,JPA如果与SpringData结合起来,会发出不一样的“化学反应”,大家拭目以待〜
官方网站对 SpringData JPA的特点描述:(SpringData JPA)
一,JPA概述
1. Java持久性API(Java持久层API):用于对象持久化的API
2.作用:使得应用程序以统一的方式访问持久层
3。前言中提到了Hibernate,那么JPA与Hibernate的关系是什么关系呢:
1)JPA是Hibernate的一个抽象,就像JDBC和JDBC驱动的关系
2)JPA是一种ORM规范,是Hibernate功能的一个子集(既然JPA是规范,Hibernate对JPA进行了扩展,那么说JPA是Hibernate的一个子集不为过)
3)Hibernate是JPA的一个实现
4。JPA包括三个方面的技术:
1)ORM映射元数据,支持XML和JDK注解两种元数据的形式
2)JPA的API
3)查询语言:JPQL
二、项目框架搭建
1.新建springboot项目
二,代码管理
1.创建Userinfo实体类
package cn.liumce.springbootjpa.entity;
import javax.persistence。*;
/ **
* @Entity:代表这个类是一个实体类
* @Table(name =“userinfos):这个注解代表对应表的名称,userinfos就是利用jpa要生成的表名称
* @id:表示此属性是主键
* @GeneratedValue:表示的是主键生成策略,默认主键是自增长的,当然你也可以用uuid
* @Column:表明此属性在数据库中对应的字段,如果实体中的属性与数据库的字段一样,可以省略不写。
* /
@实体
@Table(name =“userinfos”)
公共类Userinfo {
@ID
@GeneratedValue
@Column(name =“id”)
private Integer id; //主键
@Column(name =“user_name”)
私有String用户名; //用户名
@Column(name =“user_pass”)
private String userpass; //密码
public Integer getId(){
返回id;
}
public void setId(Integer id){
this.id = id;
}
public String getUsername(){
返回用户名;
}
public void setUsername(String username){
this.username = username;
}
public String getUserpass(){
return userpass;
}
public void setUserpass(String userpass){
this.userpass = userpass;
}
}
2.控制器在包中创建³³ 的的IndexController类
package cn.liumce.springbootjpa.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
//此注解默认返回JSON数据
@RestController
//返回页面
// @控制器
公共类IndexController {
@RequestMapping( “索引”)
public String index(){
回归“你好世界”;
//返回“index”;
}
}
3.在库包中创建UserinfoRepository类
package cn.liumce.springbootjpa.repository;
import cn.liumce.springbootjpa.entity.Userinfo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.transaction.annotation.Transactional;
/ *
实现增删改查
@Transactional开启事务
@Modifying修改方法专用注解
@Query(“”)书写JPAsql语句,其中Userinfo是实体类名,
为userpass和ID是实体类的属性名,
?1代表是第一个参数?2是第二个参数。
* /
public interface UserinfoRepository扩展了JpaRepository <Userinfo,Integer> {
@Transactional
@Modifying
@Query(“apdate Userinfo u set u.userpass =?1其中u.id =?2”)
int updateById(String userpass,int id);
}
4.我的application.properties是这样的:
#服务器端口
server.port = 8080
spring.datasource.url = JDBC:MySQL的://127.0.0.1:3306 /分贝了useUnicode =真的characterEncoding = UTF-8
spring.datasource.username =根
spring.datasource.password = 1
spring.datasource.driver类名= com.mysql.jdbc.Driver
################################################## ######
### Java Persistence Api - Spring jpa的配置信息
#其实这个hibernate.hbm2ddl.auto参数的作用主要用于:自动创建|更新|验证数据库表结构,有四个值
#create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的模型类再重新来生成新表,哪怕两次没有任何改变也要这样执行,
#这就是导致数据库表数据丢失的一个重要原因。
#create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
#UPDATE:最常用的属性,第一次加载休眠时根据模型类会自动建立起表的结构(前提是先建立好数据库),
#以后加载hibernate时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。
#要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
#validate:每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
#dialect主要是指定生成表名的存储引擎为InneoDB
#show-sql是否打印出自动生产的SQL,方便调试的时候查看
################################################## ######
spring.jpa.properties.hibernate.hbm2dd1.auto =更新
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-SQL =真
#页面默认前缀目录
spring.mvc.view.prefix = / WEB-INF /视图/
#页面默认后缀目录
spring.mvc.view.suffix = .JSP
5.pom.xml文件
<?xml version =“1.0”encoding =“UTF-8”?>
<project xmlns =“http://maven.apache.org/POM/4.0.0”xmlns:xsi =“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation =“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
<modelVersion> 4.0.0 </ modelVersion>
<的groupId> cn.liumce </的groupId>
<artifactId的> springboot-JPA </ artifactId的>
<版本> 0.0.1-SNAPSHOT </版本>
<包装>罐</包装>
<名称> springboot-JPA </名称>
<description> Spring Boot的演示项目</ description>
<母体>
<的groupId> org.springframework.boot </的groupId>
<artifactId的>弹簧引导起动父</ artifactId的>
<版本> 1.5.14.RELEASE </版本>
<relativePath /> <! - 从存储库查找父级 - >
</父>
<性能>
<project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding>
<project.reporting.outputEncoding> UTF-8 </project.reporting.outputEncoding>
<java.version> 1.8 </java.version>
</属性>
<依赖性>
<依赖性>
<的groupId> org.springframework.boot </的groupId>
<artifactId的>弹簧引导起动数据JPA </ artifactId的>
</依赖性>
<依赖性>
<的groupId> org.springframework.boot </的groupId>
<artifactId的>弹簧引导起动的Web </ artifactId的>
</依赖性>
<依赖性>
<的groupId>的MySQL </的groupId>
<artifactId的> MySQL的连接器的Java </ artifactId的>
<范围>运行时</范围>
</依赖性>
<依赖性>
<的groupId> org.springframework.boot </的groupId>
<artifactId的>弹簧引导起动测试</ artifactId的>
<范围>测试</范围>
</依赖性>
<! - servlet依赖包 - >
<依赖性>
<的groupId>的javax.servlet </的groupId>
<artifactId的>的javax.servlet-API </ artifactId的>
<范围>提供</范围>
</依赖性>
<! - JSTL(JSP标准标签库)JSP标准标签库 - >
<依赖性>
<的groupId>的javax.servlet </的groupId>
<artifactId的> JSTL </ artifactId的>
</依赖性>
<! - Tomcat的支持 - >
<依赖性>
<的groupId> org.springframework.boot </的groupId>
<artifactId的>弹簧引导起动的Tomcat </ artifactId的>
</依赖性>
<依赖性>
<的groupId> org.apache.tomcat.embed </的groupId>
<artifactId的> Tomcat的嵌入-碧玉</ artifactId的>
</依赖性>
</依赖>
<建立>
<插件>
<插件>
<的groupId> org.springframework.boot </的groupId>
<artifactId的>弹簧引导行家-插件</ artifactId的>
</插件>
</插件>
</建造>
</项目>
6.如果你返回的是页面,那么在模块里添加网络服务器,更改路径后在WEB-INF /观点下创建的jsp界面。再到控制器类中修改,将注解@RestController改为@Controller。
注:这里@RestController与@Controller的区别:
@RestController是一个结合@ResponseBody和@Controller的构造型注释。
意思是:
@RestController注解相当于@ResponseBody + @Controller合在一起的作用。
1)如果只是使用@RestController注解Controller,则Controller中的方法无法返回jsp页面,配置的视图解析器InternalResourceViewResolver不起作用,返回的内容就是返回里的内容。
例如:本来应该到的success.jsp页面的,则其显示成功。
2)如果需要返回到指定页面,则需要用@Controller配合视图解析器InternalResourceViewResolver才行。
3)如果需要返回JSON,XML或自定义mediaType的内容到页面,则需要在对应的方法上加上@ResponseBody注解。
三,测试
1.找到UserinfoRepository类,如图操作
2.在测试包生成的UserinfoRepositoryTest测试类中,做对数据库的增删改查测试。
package cn.liumce.springbootjpa.repository;
import cn.liumce.springbootjpa.entity.Userinfo;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import static org.junit.Assert。*;
@RunWith(SpringRunner.class)
//例如你的主方法的应用程序是xxxApplication.java,classes就要等于xxxApplication.class
@SpringBootTest(classes = SpringBootApplication.class)
公共类UserinfoRepositoryTest {
/ **
*添加@Autowired
*自动注入UserinfpRespository
* /
@Autowired
private UserinfoRepository userinfoRepository;
/ **
*向数据库中增加一条数据
* @Test代表这是一个测试方法
* /
@测试
public void save(){
//创建对象并实例化
Userinfo userinfo = new Userinfo();
userinfo.setUsername( “管理员”);
userinfo.setUserpass( “123456”);
//调用JPA中的保存方法,向数据库中增加一条数据,返回一个对象
Userinfo us = userinfoRepository.save(userinfo);
//断言
Assert.assertEquals(us.getUsername(), “管理员”);
}
/ **
*删除数据库的一条数据
* /
@测试
public void delete(){
//调用删除方法,根据ID删除
userinfoRepository.delete(1);
}
/ **
*更新数据库指定id数据
* /
@测试
public void update(){
userinfoRepository.updateById( “为admin123”,5);
}
@测试
public void select(){
//第一种查询返回List集合
List <Userinfo> lists = userinfoRepository.findAll();
for(Userinfo us:lists){
的System.out.println( “>>>>>>>>>>>>>>>>>>第一种,用户名是:” + us.getUsername());
}
//第二种查询根据id查询返回实体
Userinfo uinfo = userinfoRepository.findOne(5);
的System.out.println( “>>>>>>>>>>>>>>>>>>第二种,用户名是:” + uinfo.getUsername());
}
}
3.运行判断测试是否成功,可在数据表中查看是否创建表,增加数据,控制台中查看是否更新数据,可查看数据。