JPA
JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。
Spring Date整合jpa
Spring Date
pring Data是Spring的一个子项目,用于简化数据访问,包括NoSQL非关系型数据库,另外还包括对关系型数据库的访问支持。Spring Data使我们可以快速简单地使用普通的数据技术及新的数据访问技术,Spring Data会让数据的访问变得更加方便。
Spring Date jpa简介
-
Spring Data JPA是Spring基于ORM框架、JPA规范的基础上封装的一套JPA应用框架,可以让开发者用极简的代码即可实现对数据的访问和操作。Spring Data JPA其实就是Spring基于Hibrenate之上构建的JPA使用解决方案,方便在Spring Boot项目中使用JPA技术。
-
Spring Data JPA让我们解脱了DAO层的操作,基本上所有CRUD都可以依赖于它实现。
Spring Data 与 Spring Data JPA的关系:关系
1.maven开发环境配置
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>com</groupId>
<artifactId>days66SpringDataJPA</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- Spring Data JPA-->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.11.0.RELEASE</version>
</dependency>
<!--hibernate 实现JPA的框架-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.2.5.Final</version>
</dependency>
<!-- 数据源与MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.28</version>
</dependency>
<!-- Spring测试框架 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
2.在resources下创建Spring JPA配置文件
spring-datajpa.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:repository="http://www.springframework.org/schema/data/repository"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/data/repository http://www.springframework.org/schema/data/repository/spring-repository.xsd">
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置自动扫描的包 -->
<context:component-scan base-package="com.qfxa.service"/>
<context:component-scan base-package="com.qfxa.dao"/>
<!-- 数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- jpa实现框架 -->
<bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="showSql" value="true"/>
</bean>
<!-- spring-data-jpa配置 本地容器实体管理工厂对象,并指定POJO类 -->
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="packagesToScan" value="com.qfxa.po"/>
<property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
<property name="jpaProperties">
<props>
<!-- <prop key="hibernate.hbm2ddl.auto">validate</prop>-->
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<bean id="jpaTx" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf"/>
</bean>
<!-- 设置自动注解事务驱动 -->
<tx:annotation-driven proxy-target-class="false" transaction-manager="jpaTx"/>
<!-- 启动仓库扫描 -->
<jpa:repositories base-package="com.qfxa.dao"
entity-manager-factory-ref="emf"
transaction-manager-ref="jpaTx"/>
</beans>
jdbc.properties
jdbc.url=jdbc:mysql://localhost:3306/days1009?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root
jdbc.driver=com.mysql.jdbc.Driver
3.根据配置文件的扫描包名新建包
4.编码
4.1新建实体类
Profession.java
package com.qfxa.po;
import lombok.Data;
import javax.persistence.*;
@Data
@Entity
public class Profession {
//@Entity @Id基本映射注解 @GeneratedValue ID生成策略
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int pid;
//@Column设置正向工程创建数据库对字段的设置
@Column(length = 20, unique = true, name = "col_pname")
private String pname;
@Column(length = 50, unique = true, name = "col_pdesc", nullable = false)
private String pdesc;
}
4.2创建Dao接口
IProFessionDao.java
package com.qfxa.dao;
import com.qfxa.po.Profession;
import org.springframework.data.jpa.repository.JpaRepository;
import java.io.Serializable;
public interface IProFessionDao extends JpaRepository<Profession, Serializable> {
//两个参数 第一个参数实体类 第二个参数id对应的泛型Interger或者序列化接口,不能写int因为泛型只能是包装类型也可以写Number是其父类
}
4.3编写Service层
接口
package com.qfxa.service;
import com.qfxa.po.Profession;
import java.util.List;
public interface IProfessionService {
List<Profession> getAll();
Profession getProfessionByPid(int pid);
boolean saveProfession(Profession p);
boolean updateProfession(Profession p);
boolean deleteProfession(int pid);
}
接口实现类
package com.qfxa.service.impl;
import com.qfxa.dao.IProFessionDao;
import com.qfxa.po.Profession;
import com.qfxa.service.IProfessionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProfessionService implements IProfessionService {
//类型注入@Autowired 另一种方式名字注入@Qualifier
@Autowired
private IProFessionDao ipd;
@Override
public List<Profession> getAll() {
return ipd.findAll();
}
@Override
public Profession getProfessionByPid(int pid) {
return ipd.findOne(pid);
}
@Override
public boolean saveProfession(Profession p) {
return ipd.saveAndFlush(p) != null;
}
@Override
public boolean updateProfession(Profession p) {
return ipd.saveAndFlush(p) != null;
}
@Override
public boolean deleteProfession(int pid) {
try {
ipd.delete(pid);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
//查找单个用findone 不用getone
}
5.Spring单元测试
TestProfessionService.java
package com.qfxa.service;
import com.qfxa.po.Profession;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)//让测试运行于Spring测试环境
@ContextConfiguration("classpath:spring-datajpa.xml")// Spring整合JUnit4测试时,使用注解引入多个配置文件
public class TestProfessionService {
@Autowired
private IProfessionService ips;
@Test
public void testGetAll(){
List<Profession> list = ips.getAll();
for (Profession p : list) {
System.out.println(p);
}
}
@Test
public void testSaveProfession(){
Profession p = new Profession();
//如果id存在则修改 不存在则新增
p.setPid(3);
p.setPname("999988");
p.setPdesc("999999988");
System.out.println(ips.saveProfession(p));
}
}
6.正向工程
(pojo创建好后 数据库都不用创建了,自动创建实体类对应的表)
在spring-datajpa.xml配置文件中添加
<props>
<prop key="hibernate.hbm2ridu.auto">create</prop>
</ props>
- create(用于测试) 干掉表后创建
- create-drop(用于测试)干掉-创建-干掉
- update 如果没有表创建表,有表插入ID相同则修改,ID不同则添加
- validate 必须在有表的条件下才能继续操作 无表报错 有表继续操作执行新增,自动创建表
7.在正向工程前,需存在一数据库与配置文件中的数据库相对应。
执行插入测试方法,查看控制台与正向工程生成表的效果
//控制台自动生成的SQL语句
Hibernate:
create table Profession (
pid integer not null auto_increment,
col_pdesc varchar(50) not null,
col_pname varchar(20),
primary key (pid)
)
Hibernate:
alter table Profession
drop constraint UK_jg7g2cv1pme2g2p6cwuot1oqs
Hibernate:
alter table Profession
add constraint UK_jg7g2cv1pme2g2p6cwuot1oqs unique (col_pdesc)
Hibernate:
alter table Profession
drop constraint UK_quao7gtkcrsvwrof6oj230ugg
Hibernate:
alter table Profession
add constraint UK_quao7gtkcrsvwrof6oj230ugg unique (col_pname)
Hibernate:
select
profession0_.pid as pid1_0_0_,
profession0_.col_pdesc as col_pdes2_0_0_,
profession0_.col_pname as col_pnam3_0_0_
from
Profession profession0_
where
profession0_.pid=?
Hibernate:
insert
into
Profession
(col_pdesc, col_pname)
values
(?, ?)
true
Process finished with exit code 0
8.对于dao层需要根据需求查询的需要手动创建方法并且方法的命名必须遵循查询规则
查询方法规则
- findAll()查询所有
- findByXXX(Object xxx) 根据属性名等值查询
- findByXXXAndYYY(Object xxx,Object yyy) 同时满足两个属性名与属性相同的查询
- findByXXXOrYYY(Object xxx,Object yyy) 只要满足两个属性名与属性相同的任一条查询
- 除了And和Or之外,还可使用的关键字
案例
8.1新建班级实体类
package com.qfxa.po;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.io.Serializable;
@Entity
@Data
public class Clazz implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int cid;
private String cname;
private String pname;
private String cdesc;
}
8.2dao层
IClazzDao.java
package com.qfxa.dao;
import com.qfxa.po.Clazz;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface IClazzDao extends JpaRepository<Clazz, Integer> {
List<Clazz> findByPname(String pname);
List<Clazz> findByPnameAndCdesc(String pname, String cdesc);
List<Clazz> findByPnameOrCdesc(String pname, String cdesc);
List<Clazz> findByCidBetween(int min, int max);
Page<Clazz> findByPname(String pname, Pageable p);
}
8.3service层
IClazzService.java
package com.qfxa.service;
import com.qfxa.po.Clazz;
import java.util.List;
public interface IClazzService {
List<Clazz> getAllClazz();
Clazz getClazzByCid(int cid);
List<Clazz> getClazzByPname(String name);
List<Clazz> getClazzByPnameAndCdesc(String name, String cdesc);
List<Clazz> getClazzByCidBetween(int min, int max);
List<Clazz> getClazzByPnameAndPage(String pname, int cp, int ps);
}
接口实现类
package com.qfxa.service.impl;
import com.qfxa.dao.IClazzDao;
import com.qfxa.po.Clazz;
import com.qfxa.service.IClazzService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ClazzServiceImpl implements IClazzService {
@Autowired
private IClazzDao icd;
@Override
public List<Clazz> getAllClazz() {
return icd.findAll();
}
@Override
public Clazz getClazzByCid(int cid) {
return icd.getOne(cid);
}
@Override
public List<Clazz> getClazzByPname(String name) {
return icd.findByPname(name);
}
@Override
public List<Clazz> getClazzByPnameAndCdesc(String name, String cdesc) {
return icd.findByPnameOrCdesc(name, cdesc);
}
@Override
public List<Clazz> getClazzByCidBetween(int min, int max) {
return icd.findByCidBetween(min, max);
}
@Override
public List<Clazz> getClazzByPnameAndPage(String pname, int cp, int ps) {
Pageable p = new PageRequest(cp, ps);
Page<Clazz> page = icd.findByPname(pname, p);
return page.getContent();
}
}
8.4Spring测试类
package com.qfxa.service;
import com.qfxa.po.Clazz;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-datajpa.xml")
public class TestClazzService {
@Autowired
private IClazzService ics;
@Test
public void testGetAllClazz(){
List<Clazz> list = ics.getAllClazz();
for (Clazz c : list) {
System.out.println(c);
}
}
@Test
public void testGetClazzByCid(){
Clazz c = ics.getClazzByCid(10);
System.out.println(c);
}
@Test
public void testGetClazzByPname(){
for (Clazz c : ics.getClazzByPname("软件工程")) {
System.out.println(c);
}
}
@Test
public void testGetClazzByPnameAndCdesc(){
List<Clazz> list = ics.getClazzByPnameAndCdesc("软件工程", "隶属于土木工程专业的班级");
for (Clazz c : list) {
System.out.println(c);
}
}
@Test
public void testGetClazzByCidBetween(){
List<Clazz> list = ics.getClazzByCidBetween(10, 14);
for (Clazz c : list) {
System.out.println(c);
}
}
@Test
public void getGetClazzByPage(){
List<Clazz> list = ics.getClazzByPnameAndPage("软件工程", 0, 1);
for (Clazz c : list) {
System.out.println(c);
}
}
}
SpringBoot整合JPA
1.搭建SpringBoot环境:SpringBoot环境搭建
- maven方式
- 下载jar包方式
- 联网创建方式
2.添加依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
3.新建application.yml文件并配置
- 连接数据库的配置driver可不配置
- jpa配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver: =com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/days1009?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
username: root
password: root
jpa:
database: mysql
show-sql: true
hibernate:
ddl-auto: validate
properties:
hibernate:
format_sql: true
4.编写代码
4.1pojo
package com.pojo;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.io.Serializable;
@Entity
@Data
public class Clazz implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int cid;
private String cname;
private String pname;
private String cdesc;
}
4.2dao层
IClazzDao.java
package com.dao;
import com.qfedu.days67_spt_jpa.pojo.Clazz;
import org.springframework.data.jpa.repository.JpaRepository;
public interface IClazzDao extends JpaRepository<Clazz, Integer> {
}
4.3service层
package com.service;
import com.pojo.Clazz;
import java.util.List;
public interface IClazzServic {
List<Clazz> getAllClazz();
Clazz getClazzByCid(int cid);
boolean updateClazz(Clazz c);
}
接口实现类
package com.impl;
import com.dao.IClazzDao;
import com.pojo.Clazz;
import com.service.IClazzServic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ClazzServiceImpl implements IClazzServic {
@Autowired
private IClazzDao icd;
@Override
public List<Clazz> getAllClazz() {
return icd.findAll();
}
@Override
public Clazz getClazzByCid(int cid) {
return icd.getOne(cid);
}
@Override
public boolean updateClazz(Clazz c) {
try {
icd.saveAndFlush(c);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
}
4.4controller层
package com.controller;
import com.pojo.Clazz;
import com.service.IClazzServic;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("clazz")
public class ClazzController {
@Autowired
private IClazzServic ics;
@GetMapping("all")
public List<Clazz> getAllClazz(){
return ics.getAllClazz();
}
}