SpringBoot整合JPA

本文详细介绍了Java Persistence API (JPA) 的基本使用方法及如何进行扩展。从配置数据源开始,逐步展示实体定义、关系映射、自定义查询等核心功能。并通过具体示例演示了如何创建实体类、Repository接口以及控制器来实现CRUD操作。此外,文章还介绍了如何通过自定义接口和实现类来扩展JPA的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JPA 规范

 

JPA 1.0整合查询语言(Query)和对象关系映射(ORM)元数据定义

JPA 2.0在1.0的基础上,增加Criteria查询,元数据API以及校验支持

 

实体(Entities)

约束:

a 实体类必须使用@Entity标注或者XML描述

b 实体类至少包含一个默认构造器,并且构造器必须是public 或者 protected

c 实体必须是顶级类,不能是枚举或者接口

d 实体类禁止是final类

c 实体支持继承,多态关联 以及多态查询

 

实体持久字段和属性

实体持久状态由字段(Fields)或者(Properties),字段即实例的属性或变量,属性则是JavaBeans实例的setter或getter方法

实例字段的访问级别必须是private,protected 或者 包可见,属性(getter, setter)的可见性必须是public或者protected

字段和属性可能是单一类型值或集合类型值

 

字段和属性访问类型(Access Type)是通过字段访问 还是 通过属性 访问

默认访问类型 (不需要持久化)

非transient 或者 @Transient 字段

非 @Transient属性

显示访问类型

注解类型

a 实体类

b 映射超类

c 嵌套类

 

注解

a @Access(AccessType.FIELD)字段

b @Access(AccessType.PROPERTY)属性

 

 

实体主键(Primary Key)

每个实体必须存在主键,主机必须定义在实体类

a 简单主键 @Id

b 复合主键 @EmbeddedId @IdClass

 

 

实体关系

实体关系可能一对一,一对多,多对一 或 多对多,这些关系是多态性的,可以是单向或者双向

 

注解表述方式

@OneToOne

@OneToMany

@ManyToOne

@ManyToMany

 

XML表述方式

@Embeddedle

@IdClass

 

版本 springboot 1.5.9

 

基本使用

第一步 配置数据源

datasource:

driver-class-name: com.mysql.jdbc.Driver

url: jdbc:mysql://localhost:3306/dbgirl

username: root

password: root

type: com.alibaba.druid.pool.DruidDataSource

initialSize: 5

minIdle: 5

maxActive: 20

maxWait: 60000

timeBetweenEvictionRunsMillis: 60000

minEvictableIdleTimeMillis: 300000

validationQuery: SELECT 1 FROM DUAL

testWhileIdle: true

testOnBorrow: false

testOnReturn: false

maxPoolPreparedStatementPerConnectionSize: 20

# 打开PSCache ,并且指定每个连接上PSCache的大小

poolPreparedStatements: true

# 配置监控统计拦截的filters,去掉后监控界面sql将无法统计,'wall'用于防火墙

filters: stat,wall,log4j

# 通过connectionProperties属性来打开mergeSql 功能,慢SQL 记录

connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

jpa:

hibernate:

ddl-auto: update

show-sql: true

 

application

package cn.sd.girl;

 

import cn.sd.girl.girl.interceptor.DefaultInterceptor;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.boot.web.servlet.ErrorPage;

import org.springframework.boot.web.servlet.ErrorPageRegistrar;

import org.springframework.boot.web.servlet.ErrorPageRegistry;

import org.springframework.http.HttpStatus;

import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

 

 

@SpringBootApplication

public class GirlApplication extends WebMvcConfigurerAdapter implements ErrorPageRegistrar{

 

public static void main(String[] args) {

 

SpringApplication.run(GirlApplication.class, args);

}

 

}

 

 

编写 doMain

 

package cn.sd.girl.jpa.doMain;

 

import javax.persistence.*;

import java.io.Serializable;

 

@Entity

@Table(name = "deparment")

public class Deparment implements Serializable{

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

private String name;

 

public Deparment(){}

 

@Override

public String toString() {

return "Deparment{" +

"id=" + id +

", name='" + name + '\'' +

'}';

}

 

public Long getId() {

return id;

}

 

public void setId(Long id) {

this.id = id;

}

 

public String getName() {

return name;

}

 

public void setName(String name) {

this.name = name;

}

}

package cn.sd.girl.jpa.doMain;

 

import javax.persistence.*;

import java.io.Serializable;

 

@Entity

@Table(name="role")

public class Role implements Serializable{

 

public Role() {

}

 

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

private String name;

 

public Long getId() {

return id;

}

 

public void setId(Long id) {

this.id = id;

}

 

public String getName() {

 

return name;

}

 

public void setName(String name) {

this.name = name;

}

 

@Override

public String toString() {

return "Role{" +

"id=" + id +

", name='" + name + '\'' +

'}';

}

}

package cn.sd.girl.jpa.doMain;

 

import com.fasterxml.jackson.annotation.JsonBackReference;

import org.springframework.format.annotation.DateTimeFormat;

 

import javax.persistence.*;

import java.io.Serializable;

import java.util.Date;

import java.util.List;

 

@Entity

@Table(name = "user")

public class User implements Serializable{

@Id

@GeneratedValue(strategy = GenerationType.IDENTITY)

private Long id;

private String name;

@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")

private Date createDate;

@ManyToOne

@JoinColumn(name = "did")

@JsonBackReference //防止关系对象的递归访问

private Deparment deparment;

 

/*

cascade 默认被级联,

eager 非懒加载

*/

@ManyToMany(cascade = {},fetch = FetchType.EAGER)

@JoinTable(name = "user_role",joinColumns = {@JoinColumn(name = "user_id")},

inverseJoinColumns = {@JoinColumn(name = "roles_id")}) // 外键

private List<Role> roles;

 

 

@Override

public String toString() {

return "User{" +

"id=" + id +

", name='" + name + '\'' +

", createDate=" + createDate +

", deparment=" + deparment +

", roles=" + roles +

'}';

}

 

public Long getId() {

return id;

}

 

public void setId(Long id) {

this.id = id;

}

 

public String getName() {

return name;

}

 

public void setName(String name) {

this.name = name;

}

 

public Date getCreateDate() {

return createDate;

}

 

public void setCreateDate(Date createDate) {

this.createDate = createDate;

}

 

public Deparment getDeparment() {

return deparment;

}

 

public void setDeparment(Deparment deparment) {

this.deparment = deparment;

}

 

public List<Role> getRoles() {

return roles;

}

 

public void setRoles(List<Role> roles) {

this.roles = roles;

}

 

public User() {

}

}

 

 

编写 repository

package cn.sd.girl.jpa.repository;

 

import cn.sd.girl.jpa.doMain.Deparment;

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.stereotype.Repository;

 

@Repository

public interface DepartmentRepository extends JpaRepository<Deparment,Long>{

}

package cn.sd.girl.jpa.repository;

import cn.sd.girl.jpa.doMain.Role;

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.stereotype.Repository;

 

@Repository

public interface RoleRepository extends JpaRepository<Role,Long>{

}

package cn.sd.girl.jpa.repository;

 

import cn.sd.girl.jpa.doMain.User;

import org.springframework.data.domain.Page;

import org.springframework.data.domain.Pageable;

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.jpa.repository.Query;

import org.springframework.data.repository.query.Param;

import org.springframework.stereotype.Repository;

/*

JPA 还提供了一些自定义方法的规章,例如,在接口中使用关键字findBy

,readBy,getBy作为方法名的前缀,拼接实体类中的属性字段(首个字母大写),

并可选择拼接一些SQL查询关键字组合成一个查询方法

*/

@Repository

public interface UserRepository extends JpaRepository<User,Long>{

// And

User findByIdAndName(Long id, String name);

 

 

/*

@Query 来定义一些简单的查询语句

*/

@Query("select t from User t where t.name like :name")

Page<User> findByName(@Param("name") String name, Pageable pageable);

 

 

}

 

 

 

 

编写 controller

package cn.sd.girl.jpa.controller;

 

import cn.sd.girl.girl.ExceptionEnum;

import cn.sd.girl.girl.domain.Girl;

import cn.sd.girl.girl.exception.GirlException;

import cn.sd.girl.girl.repository.GirlRepository;

import cn.sd.girl.jpa.doMain.Deparment;

import cn.sd.girl.jpa.doMain.Role;

import cn.sd.girl.jpa.doMain.User;

import cn.sd.girl.jpa.repository.DepartmentRepository;

import cn.sd.girl.jpa.repository.RoleRepository;

import cn.sd.girl.jpa.repository.UserRepository;

import com.alibaba.druid.pool.DruidDataSource;

import com.alibaba.druid.support.jconsole.DruidDataSourcePanel;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.domain.Page;

import org.springframework.data.domain.PageRequest;

import org.springframework.data.domain.Pageable;

import org.springframework.data.domain.Sort;

import org.springframework.util.Assert;

import org.springframework.validation.BindingResult;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

 

import javax.validation.Valid;

import java.util.Date;

import java.util.List;

 

@RestController

public class JpaController {

 

private static Logger logger = LoggerFactory.getLogger(JpaController.class);

@Autowired

UserRepository userRepository;

@Autowired

DepartmentRepository departmentRepository;

@Autowired

RoleRepository roleRepository;

 

 

@RequestMapping(value = "befor")

public void befor(){

userRepository.deleteAll();

roleRepository.deleteAll();

departmentRepository.deleteAll();

 

Deparment deparment = new Deparment();

deparment.setName("开发部");

departmentRepository.save(deparment);

Assert.notNull(deparment.getId());

Role role = new Role();

role.setName("admin");

roleRepository.save(role);

Assert.notNull(role.getId());

 

User user = new User();

user.setName("user");

user.setCreateDate(new Date());

user.setDeparment(deparment);

 

List<Role> roles = roleRepository.findAll();

Assert.notNull(roles);

user.setRoles(roles);

 

 

userRepository.save(user);

Assert.notNull(user.getId());

}

 

@RequestMapping(value = "findPage")

public void findPage(){

 

Pageable pageable = new PageRequest(0,10,new Sort(Sort.Direction.ASC,"id"));

 

Page<User> page = userRepository.findAll(pageable);

 

Assert.notNull(page);

 

User u = userRepository.findByIdAndName(new Long(1),"user");

 

Page<User> user1 = userRepository.findByName("user", pageable);

 

 

logger.info("u:"+u);

 

for(User user : user1.getContent()){

logger.info("==============user=======user name:{},department name:{},role name:{}",

user.getName(),user.getDeparment(),user.getRoles());

}

}

 

}

 

 

 

 

 

 

 

 

 

 

运行结果

2018-07-23 10:49:38.127 INFO 4368 --- [nio-8081-exec-1] cn.sd.girl.jpa.controller.JpaController : u:User{id=1, name='user', createDate=null, deparment=Deparment{id=1, name='开发部'}, roles=[Role{id=1, name='admin'}]}

2018-07-23 10:49:38.127 INFO 4368 --- [nio-8081-exec-1] cn.sd.girl.jpa.controller.JpaController : ==============user=======user name:user,department name:Deparment{id=1, name='开发部'},role name:[Role{id=1, name='admin'}]

2018-07-23 10:49:38.127 INFO 4368 --- [nio-8081-exec-1] cn.sd.girl.jpa.controller.JpaController : ==============user=======user name:user,department name:Deparment{id=1, name='开发部'},role name:[Role{id=1, name='admin'}, Role{id=3, name='普通用户'}, Role{id=4, name='admin'}]

扩展JPA

第一部 编写 扩展类 接口

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.repository.NoRepositoryBean;

 

import java.io.Serializable;

@NoRepositoryBean

public interface ExpandJpaRepository<T, ID extends Serializable> extends JpaRepository<T,ID> {

 

T findOne(String sql, Object... objects);

}

 

 

编写扩展类实现

import org.springframework.data.jpa.repository.query.QueryUtils;

import org.springframework.data.jpa.repository.support.JpaEntityInformation;

import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

 

import javax.persistence.EntityManager;

import javax.persistence.Query;

import java.io.Serializable;

import java.util.Iterator;

 

public class ExpandJpaRepositoryImpl<T,ID extends Serializable>

extends SimpleJpaRepository<T,ID> implements ExpandJpaRepository<T,ID> {

 

 

private final EntityManager entityManager;

private final JpaEntityInformation<T, ?> entityInformation;

 

public ExpandJpaRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {

super(entityInformation, entityManager);

this.entityManager = entityManager;

this.entityInformation = entityInformation;

}

 

private void applyQueryParameter(Query query,Object... objects){

if(objects!=null){

int i = 0;

for(Object value:objects){

i++;

query.setParameter(i,value);

}

}

}

 

@Override

public T findOne(String sql, Object... objects) {

Query query = entityManager.createQuery(sql);

 

applyQueryParameter(query,objects);

 

 

 

 

 

T result = (T)query.getSingleResult();

return result;

}

 

 

}

 

 

编写装配类 getTargetRepository 就是返回 ExpandJpaRepositoryImpl

import org.springframework.data.jpa.repository.JpaRepository;

import org.springframework.data.jpa.repository.support.JpaEntityInformation;

import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;

import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;

import org.springframework.data.repository.core.RepositoryMetadata;

import org.springframework.data.repository.core.support.RepositoryFactorySupport;

 

import javax.persistence.EntityManager;

import java.io.Serializable;

 

public class ExpandJpaRepositoryFactoryBean<R extends JpaRepository<T, ID>, T, ID extends Serializable>

extends JpaRepositoryFactoryBean<R, T, ID> {

 

public ExpandJpaRepositoryFactoryBean(Class<? extends R> repositoryInterface) {

super(repositoryInterface);

}

 

protected RepositoryFactorySupport createRepositoryFactory(

EntityManager entityManager) {

return new ExpandJpaRepositoryFactory<T, ID>(entityManager);

}

 

private static class ExpandJpaRepositoryFactory<T, ID extends Serializable>

extends JpaRepositoryFactory {

 

private final EntityManager entityManager;

 

public ExpandJpaRepositoryFactory(EntityManager entityManager) {

 

super(entityManager);

this.entityManager = entityManager;

}

 

protected Object getTargetRepository(RepositoryMetadata metadata) {

JpaEntityInformation<T, Serializable> entityInformation = (JpaEntityInformation<T, Serializable>) getEntityInformation(metadata.getDomainType());

return new ExpandJpaRepositoryImpl<T, ID>(entityInformation, entityManager);

}

 

protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {

return ExpandJpaRepositoryImpl.class;

}

}

}

 

 

编写 配置类,加载自定义装配 类

import cn.sd.girl.jpa.repository.ExpandJpaRepositoryFactoryBean;

import org.springframework.boot.autoconfigure.domain.EntityScan;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.Ordered;

import org.springframework.core.annotation.Order;

import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;

import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import org.springframework.transaction.annotation.EnableTransactionManagement;

 

@Order(Ordered.HIGHEST_PRECEDENCE)

@Configuration

@EnableTransactionManagement(proxyTargetClass = true)

@EnableJpaRepositories(basePackages = "cn.sd.girl.jpa.repository",repositoryFactoryBeanClass = ExpandJpaRepositoryFactoryBean.class)

@EntityScan(basePackages = "cn.sd.girl.jpa.doMain")

public class JpaConfiguration {

@Bean

PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(){

return new PersistenceExceptionTranslationPostProcessor();

}

}

 

 

UserRepository 继承的就是 前面定义的接口ExpandJpaRepositoy,使用JPA 扩展接口与使用原来的JPA接口一样,调用方法基本相同,可以使用 扩展接口 抽象一些通用的方法,能使用 更灵活

@Repository

public interface UserRepository extends ExpandJpaRepository<User,Long>{

// And

User findByIdAndName(Long id, String name);

 

 

/*

@Query 来定义一些简单的查询语句

*/

@Query("select t from User t where t.name like :name")

Page<User> findByName(@Param("name") String name, Pageable pageable);

 

 

}

 

 

使用 接口

 

package cn.sd.girl.jpa.controller;

 

import cn.sd.girl.girl.ExceptionEnum;

import cn.sd.girl.girl.domain.Girl;

import cn.sd.girl.girl.exception.GirlException;

import cn.sd.girl.girl.repository.GirlRepository;

import cn.sd.girl.jpa.doMain.Deparment;

import cn.sd.girl.jpa.doMain.Role;

import cn.sd.girl.jpa.doMain.User;

import cn.sd.girl.jpa.repository.DepartmentRepository;

import cn.sd.girl.jpa.repository.RoleRepository;

import cn.sd.girl.jpa.repository.UserRepository;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.domain.Page;

import org.springframework.data.domain.PageRequest;

import org.springframework.data.domain.Pageable;

import org.springframework.data.domain.Sort;

import org.springframework.util.Assert;

import org.springframework.validation.BindingResult;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

 

import javax.validation.Valid;

import java.util.Date;

import java.util.List;

 

@RestController

public class JpaController {

 

private static Logger logger = LoggerFactory.getLogger(JpaController.class);

@Autowired

UserRepository userRepository;

 

@RequestMapping(value = "findOne")

public void findOne(){

String sql = "select t from User t where t.id = ?1";

User one = userRepository.findOne(sql, new Object[]{Long.valueOf(1)});

System.out.println("one:"+one);

}

 

}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值