栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java > SpringBoot

Spring-Data-Jpa使用总结

SpringBoot 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring-Data-Jpa使用总结

![](http://img3.sycdn.imooc.com/5dd38a95000100b816000900.jpg)

参考资源列表>> 1.官方文档:https : //docs.spring.io/spring-data/jpa/docs/2.1.5.RELEASE/reference/html/ > 2.“春数据JPA入门到精通”

前言

JPAJava持久性API '的简称,是'春天'在'休眠'的基础上进行的二次封装框架,为了更好更方便的融入'春天'大家庭,同时也提供了一些休眠SpringData` 没有的特性,与其他ORM框架一起构成,统一封装了ORM层,使开发人员使用起来更加方便快捷。

备注:本文所有代码都是基于SpringBoot 2.1.5版本

JPA的使用 基本单表操作的使用

对于操作单表来说,JPA提供了非常方便使用的封装,我们只需要按规范编写库接口同时继承JpaRepository就可以接受JPA基本功能了代码如下:

用户实体:

java 包 com 。一竹。实体; 进口龙目岛。建造者; 进口龙目岛。数据; 进口龙目岛。ToString ; 导入 javax 。坚持不懈。* ; 导入 java 。io 。可序列化; 导入 java 。实用程序。清单; 导入 java 。实用程序。设置;

@Entity @Table(名称= “T_USER”)@Data @Builder公共类用户器具序列化{私人静态最终长的的的serialVersionUID = 1L ; @Id @GeneratedValue(策略= GenerationType.IDENTITY)私人龙ID;私有字符串名称;专有字符串密码;私有整体时代;私人的整数性别; } 储存库接口:。java的包COM一竹仓库;引入玉米一竹实体用户。;公共接口UserRepository扩展了JpaRepository <用户,龙> { } 下面看看JPA为我们提供了一些替代操作单表数据的方法。java的包有机弹簧框架。数据。jpa。仓库; @NoRepositoryBean公共接口JpaRepository

< T , ID > 扩展了PagingAndSortingRepository < T , ID > , QueryByExampleExecutor < T > { List < T > findAll (); //查询全表数据 列表< T > findAll

(对var1排序); //查询全表数据,支持排序 List < T > findAllById ( Iterable < ID > var1 ); //根据id细分查询所有匹配数据< S 扩展T >列表< S > saveAll ( Iterable < S > var1 ); //批量保存或更新数据void flush (); //刷新本地缓存到数据库< S 扩展T > S saveAndFlush

 ( S var1 );  //保存或更新单挑数据及刷新本地缓存到数据库空隙deleteInBatch (可迭代< Ť > VAR1 ); //批量删除数据无效deleteAllInBatch (); //批量删除全表数据     T getOne ( ID var1 ); //根据id查询一条匹配数据< S 扩展T > List < S > findAll (示例< S > ar1 );//示例方式的查询指定实体<

  

  



   

S 扩展 T > List < S >  findAll (示例< S > var1 , Sort var2 ); 	//示例方式的查询指定实体并排序} ```

java 包 org 。弹簧框架。数据。仓库; @NoRepositoryBean 公共接口PagingAndSortingRepository < T , ID > 扩展CrudRepository < T , ID > { Iterable < T > findAll ( Sort var1 ); //根据排序查询全表,返回类型是任意集合 Page < T > findAll ( Pageable var1 ); //根据分页参数分页查询

} `“ java包org。弹簧框架。数据。仓库;@NoRepositoryBean公共接口CrudRepository < T,ID >扩展存储库< T,ID > { < S扩展T > S save(S var1);//保存或更新单条数据可重复 saveAll(可迭代< S > var1); //批量保存或更新可选 findById(ID var1); //根据id查询数据,,返回类型是可选的boolean existById(ID var1); //根据id判断数据是否存在Iterable findAll();//查询全表数据,返回类型为集合Iterable findAllById(Iterable var1);//根据id集合查询数据long count();//统计全表数据量void deleteById(ID var1);//根据ID删除数据无效删除(ŤVAR1);//删除单条数据void deleteAll(可迭代<?扩展T>

    		//删除指定集合数据无效的deleteAll();//删除全表数据} ```的java包有机弹簧框架数据仓库查询。。;公共接口QueryByExampleExecutor < Ť > { <小号扩展Ť >可选<小号> findOne(示例<小号> VAR1); //根据示例查询一条可迭代 findAll(示例< S > var1);//根据示例查询所有数据可重复 findAll(示例 var1,对var2排序); //根据示例查询所有数据,并排序页面 findAll (示例 var1,可分页的var2);//根据示例分页查询 long   count(示例<

; ///根据示例统计布尔值存在(示例 var1); //根据示例判断数据是否存在} 另外,jpa提供了一套新的生成sql的机制,非常方便好用,JPA根据存储库接口的方法中的关键字,实体替换及出入参,自动生成SQL,这种方式启动容器的时候就可以检查语法是否正确,简单使用示例如下:的Java 包融为一体。一竹。仓库; 导入 com 。一竹。实体。用户; 导入组织。弹簧框架。数据。jpa 。仓库。实体图; 导入组织。弹簧框架。数据。jpa。仓库。JpaRepository

; 导入组织。弹簧框架。数据。jpa 。仓库。JpaSpecificationExecutor ; 导入组织。弹簧框架。数据。jpa 。仓库。查询; 导入组织。弹簧框架。数据。仓库。查询。参数; 导入 java 。

util.List;

public interface UserRepository extends JpaRepository{

List findAllByAge(Integer age);


List findBySexAndOrg(@Param("sex") Integer sex, @Param("name") String name);


@Query(value = "from User u")
List findAll();


@Query(value = "select * from t_user u where u.user_age = ?1", nativeQuery = true)
List findAllByAge(Integer age); / **      *根据用户性别和所属组织名称查询用户信息     * @param userSex      * @param orgName      * @return      * / @Query ( value = “从用户u中选择u从u左加入u.org o其中u.userSex =: userSex和o.orgName =:orgName“ )     列表<用户> findUsersBySexAndOrg (@Param (” userSex“ )整数userSex ,@Param (” orgName“ )字符串orgName ); } ```
多表关联

@OneToOne,@OneToMany,@ManyToOne,@ManyToMany


 
   




     



     
    
    
    

     
     
    

     
     


     
     
    

     
     
    

     
     
    长orgId; @ApiModelProperty(值=“用户信息”)@oneToOne @JoinColumn(名称=“ id”,可更新= false,可插入= false)私有UserInfo userInfo;@ApiModelProperty(值=“用户所属组织”)@ManyToOne @JoinColumn(名称=“ org_id”,可更新= false,可插入= false)    私人组织机构;@ApiModelProperty(值=“用户角色”)@oneToMany @JoinColumn(名称=“ USER_ID”,referencedColumnName =“ ID”,可插入=假,可更新=假)@NotFound(动作= NotFoundAction。IGNORE)私有集<角色>角色; @ApiModelProperty(值    =“用户工作”)@ManyToMany @JoinTable(名称=“ t_user_job”,joinColumns = @JoinColumn(名称=“ user_id”,referencedColumnName =“ id”),inverseJoinColumns = @JoinColumn(名称=“ job_id”), referencedColumnName =“ id“))@ NotFound(动作= NotFoundAction。。)IGNORE)    私人集合工作;```

     
    

    

     
    



     
    
 
    
    


    
    
 
   
   
    
    



>`private Set <角色>角色;和和私订<工作>的工作;“不能用同时使用”列表代替,会报错`org.hibernate.loader.MultipleBagFetchException:不能同时获取多个袋:[com.yizhu.entity.User.jobs,com.yizhu.entity.User.roles] ` ###动态查询```java 包 com 。一竹。仓库; 导入 com 。一竹。dto 。UserQueryDto ; 导入 com 。一竹。实体。组织; 导入 com 。一竹。实体。用户; 导入组织。









弹簧框架。数据。jpa 。域。规格; 导入 javax 。坚持不懈。标准。加盟; 导入 javax 。坚持不懈。标准。JoinType ; 导入 javax 。坚持不懈。标准。谓词; 导入 java 。实用程序。ArrayList ; 导入 java 。实用程序。





清单; 导入 java 。实用程序。可选的; 公共类UserSpecs { 公共静态规范<用户> listQuerySpec ( UserQueryDto userQueryDto ){ 返回(根,查询,构建器)- > {      列表<谓词>谓词= 新ArrayList < > ();


   

      
    
  

     可选的。ofNullable ( userQueryDto 。的getId ())。ifPresent (我- >谓词。添加(助洗剂。等于(根。获得(“ID” ),我)));      可选的。ofNullable ( userQueryDto 。的getName ())。ifPresent ( ñ -
>谓词。添加(建设者。等于(根。获得(“名称” ), ñ ))); 
     可选的。ofNullable ( userQueryDto 。getAge ())。ifPresent (一- >谓词。加(建设者。等于(根。获得(“时代” ), a))); 
     可选的。ofNullable ( userQueryDto 。getOrgId ())。ifPresent ( OI - >谓词。添加(助洗剂。等于(根。获得(“ORGID” ), OI )));      可选的。ofNullable ( userQueryDto 。getOrgName ())。
ifPresent(on -> {
  Join userJoin = root.join(root.getModel().getSingularAttribute("org", Organization.class), JoinType.LEFT);
  predicates.add(builder.equal(userJoin.get("orgName"), on));
     });

     return builder.and(predicates.toArray(new Predicate[predicates.size()]));
 };
    }
}
package com.yizhu.service;

import com.yizhu.dto.UserQueryDto;
import com.yizhu.entity.User;
import com.yizhu.repository.UserRepository;
import com.yizhu.repository.UserSpecs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public List findUsersDynamic(UserQueryDto userQueryDto){
 return userRepository.findAll(UserSpecs.listQuerySpec(userQueryDto));
    }
}
审计功能使用

在启动类添加@EnableJpaAuditing注解表示开启jpa审计功能

package com.yizhu;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@SpringBootApplication
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}

在需要使用审计功能的实体类添加@EntityListeners(AuditingEntityListener.class)注释解

package com.yizhu.entity;

import lombok.Builder;
import lombok.Data;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

@Entity
@Table(name = "t_role")
@Data
@Builder
@EntityListeners(AuditingEntityListener.class)
public class Role implements Serializable {
    private static final long serialVersionUID=1L;

    @ApiModelProperty(hidden = true)
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String roleName;

    @CreatedDate
    private Date createTime;
    
	@CreatedBy
    private Long createId;
    
    @LastModifiedDate
    private Date updateTime;
    
	@LastModifiedBy
    private Long updateId;
}

实现AuditorAware接口,告诉容器当前登录人id

package com.yizhu.configuration;

import org.springframework.data.domain.AuditorAware;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Optional;

public class UserAuditorAwareImpl implements AuditorAware {
    @Override
    public Optional getCurrentAuditor() {
 // 从session中获取登录人id
 ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
 Long userId = (Long)servletRequestAttributes.getRequest().getSession().getAttribute("userId");
 return Optional.of(userId);
    }
}

ok,然后jpa将会根据IDVersion判断当前操作是更新还是添加数据,添加时会注入当前登录人id到标有@CreateBy注解的转移上,当前时间注入到标有@CreateTime注解分段上;更新时则注入到@LastModifiedBy和对应@LastModifiedDate的基线上。想详细了解的可查看org.springframework.data.jpa.domain.support.AuditingEntityListener原始代码。

常见的坑
  • N + 1问题,当使用@ManyToMany@ManyToOne@OneToMany@OneToOne关联关系的时候,FetchType怎么配置LAZY或者EAGER.SQL执行真正的时候的英文由一条主表查询和Ñ条子表查询组成的。这种查询效率一般比较低下,某些子对象有N个就会执行N + 1条SQL。使用JPA 2.1启动的@ EntityGraph,@ NamedEntityGraph可以解决该问题。如下。


 
   




     

serialVersionUID = 1L ; @ApiModelProperty (隐藏= 真)@Id @GeneratedValue (策略= GenerationType 。 IDENTITY )私人龙ID ; //省略其他属性} ```

     
    
    
    
    
    



```java
package com.yizhu.repository;

import com.yizhu.entity.User;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;

public interface UserRepository extends JpaRepository, JpaSpecificationExecutor {

    
    @EntityGraph(value = "User.findUsers", type = EntityGraph.EntityGraphType.FETCH)
    User findAllById(Long id);

    
    @EntityGraph(value = "User.findUsers", type = EntityGraph.EntityGraphType.FETCH)
    @Query(value = "select * from t_user where user_name = :name", nativeQuery = true)
    List findAllByUserName(@Param("name") String name);
}
  • 所有的注解要么全配置在字段上,要么全配置在获得方法上,不能混用,混用就会启动不起来,但是语法配置没有问题。- 所有的关联都是支持单向关联和双向关联的,- 在所有的关联查询中,表一般是不需要建立外键索引的。。在特定情况下,视听特定业务场景而定。JSON序列化的时间使用双向注解会产生死循环,需要人为手动转换一次,或者使用@JsonIgnore 。 @mappedBy的使用需要注意。- 级联删除比较危险,建议考虑清楚,或者完全掌握。- 不同的关联关系的配置,@ JoinClumn里面的名字,referencedColumnName代表的意思是不一样的,很容易弄混,可以根据打印出来的SQL做调整。- 当配置这些关联关系的时候建议大家直接在表上面,把外键建好,然后通过后面我们介绍的开发工具直接生成,这样可以减少自己调试的时间。
JPA常用注解

摘自《 Spring Data JPA从入门到精通》

![1554619508054](http://img3.sycdn.imooc.com/5dd38a980001e64909160828.jpg)

![1554619555135](http://img1.sycdn.imooc.com/5dd38a9e00017a5808980852.jpg)

![1554619583326](http://img1.sycdn.imooc.com/5dd38aa00001f81808390276.jpg)

![1554619600777](http://img3.sycdn.imooc.com/5dd38aa40001f30a08990565.jpg)

![1554619615592](http://img2.sycdn.imooc.com/5dd38aa700010ead09290574.jpg

![1554619631450](http://img1.sycdn.imooc.com/5dd38aab0001a22709330901.jpg

![1554620031094](http://img1.sycdn.imooc.com/5dd38aaf0001548009410705.jpg

![1554620213902](http://img3.sycdn.imooc.com/5dd38ab400019c5309081128.jpg

![1554620262086](http://img4.sycdn.imooc.com/5dd38ab80001d6fa09060403.jpg

更多信息可以关注我的个人博客:[逸竹小站]

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号