当前位置: 首页 > news >正文

Spring Data JPA 在 SpringBoot 应用中的简单实践

Spring Data JPA 在 SpringBoot 应用中的简单实践

    • 1.引用maven依赖
    • 2.添加配置
    • 3.定义实体类
    • 4.仓库类
        • 4.1 基本仓库 Repository
        • 4.2 CrudRepository
        • 4.3 PagingAndSortingRepository
        • 4.4 JpaRepository
    • 5.测试用例
    • 6.自定义持久化语句
        • 6.1 方法名方式
        • 6.2 编写SQL
    • 附录

1.引用maven依赖

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

2.添加配置

添加@EnableJpaRepositories注解,开启JPA功能

@SpringBootApplication
@EnableJpaRepositories
public class SpringdataDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringdataDemoApplication.class, args);
    }
}

3.定义实体类

使用@Entity对实体类进行注解

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;


@Entity(name = "t_user")
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "`t_name`")
    private String name;

    /**
     * 不使用 @Column ,默认数据库字段名就是 age
     */
    private Integer age;

    /**
     * 枚举 
     */
    @Enumerated(EnumType.STRING)
    UserStatus status;

}

4.仓库类

4.1 基本仓库 Repository


import org.springframework.data.repository.Repository;

public interface UserRepository extends Repository<User, Long> {

}

这样就可以使用UserRepository就是持久化操作了,
但是若仅仅继承Repository接口,需要自己编写很多方法。

4.2 CrudRepository

CrudRepository接口封装了常用的增删改查方法:

@NoRepositoryBean
public interface CrudRepository<T, ID> extends Repository<T, ID> {
	<S extends T> S save(S entity);
	<S extends T> Iterable<S> saveAll(Iterable<S> entities);

	Optional<T> findById(ID id);
	boolean existsById(ID id);
	Iterable<T> findAll();
	Iterable<T> findAllById(Iterable<ID> ids);

	long count();

	void deleteById(ID id);
	void delete(T entity);
	void deleteAll(Iterable<? extends T> entities);
	void deleteAll();
}

使用案例:

import org.springframework.data.repository.CrudRepository;

public interface UserRepository extends CrudRepository<User, Long> {

}

4.3 PagingAndSortingRepository

PagingAndSortingRepository提供了基本的分页方法,并继承了CrudRepository提供的增删改查方法

@NoRepositoryBean
public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> {

	Iterable<T> findAll(Sort sort);

	Page<T> findAll(Pageable pageable);
}

使用案例:

import org.springframework.data.repository.PagingAndSortingRepository;

public interface UserRepository extends PagingAndSortingRepository<User, Long> {

}

4.4 JpaRepository

/**
 * JPA specific extension of {@link org.springframework.data.repository.Repository}.
 *
 * @author Oliver Gierke
 * @author Christoph Strobl
 * @author Mark Paluch
 */
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll()
	 */
	List<T> findAll();

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.PagingAndSortingRepository#findAll(org.springframework.data.domain.Sort)
	 */
	List<T> findAll(Sort sort);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#findAll(java.lang.Iterable)
	 */
	List<T> findAllById(Iterable<ID> ids);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
	 */
	<S extends T> List<S> saveAll(Iterable<S> entities);

	/**
	 * Flushes all pending changes to the database.
	 */
	void flush();

	/**
	 * Saves an entity and flushes changes instantly.
	 *
	 * @param entity
	 * @return the saved entity
	 */
	<S extends T> S saveAndFlush(S entity);

	/**
	 * Deletes the given entities in a batch which means it will create a single {@link Query}. Assume that we will clear
	 * the {@link javax.persistence.EntityManager} after the call.
	 *
	 * @param entities
	 */
	void deleteInBatch(Iterable<T> entities);

	/**
	 * Deletes all entities in a batch call.
	 */
	void deleteAllInBatch();

	/**
	 * Returns a reference to the entity with the given identifier. Depending on how the JPA persistence provider is
	 * implemented this is very likely to always return an instance and throw an
	 * {@link javax.persistence.EntityNotFoundException} on first access. Some of them will reject invalid identifiers
	 * immediately.
	 *
	 * @param id must not be {@literal null}.
	 * @return a reference to the entity with the given identifier.
	 * @see EntityManager#getReference(Class, Object) for details on when an exception is thrown.
	 */
	T getOne(ID id);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example);

	/*
	 * (non-Javadoc)
	 * @see org.springframework.data.repository.query.QueryByExampleExecutor#findAll(org.springframework.data.domain.Example, org.springframework.data.domain.Sort)
	 */
	@Override
	<S extends T> List<S> findAll(Example<S> example, Sort sort);
}

/**
 * Interface to allow execution of Query by Example {@link Example} instances.
 *
 * @param <T>
 * @author Mark Paluch
 * @author Christoph Strobl
 * @since 1.12
 */
public interface QueryByExampleExecutor<T> {

	/**
	 * Returns a single entity matching the given {@link Example} or {@literal null} if none was found.
	 *
	 * @param example must not be {@literal null}.
	 * @return a single entity matching the given {@link Example} or {@link Optional#empty()} if none was found.
	 * @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the Example yields more than one result.
	 */
	<S extends T> Optional<S> findOne(Example<S> example);

	/**
	 * Returns all entities matching the given {@link Example}. In case no match could be found an empty {@link Iterable}
	 * is returned.
	 *
	 * @param example must not be {@literal null}.
	 * @return all entities matching the given {@link Example}.
	 */
	<S extends T> Iterable<S> findAll(Example<S> example);

	/**
	 * Returns all entities matching the given {@link Example} applying the given {@link Sort}. In case no match could be
	 * found an empty {@link Iterable} is returned.
	 *
	 * @param example must not be {@literal null}.
	 * @param sort the {@link Sort} specification to sort the results by, must not be {@literal null}.
	 * @return all entities matching the given {@link Example}.
	 * @since 1.10
	 */
	<S extends T> Iterable<S> findAll(Example<S> example, Sort sort);

	/**
	 * Returns a {@link Page} of entities matching the given {@link Example}. In case no match could be found, an empty
	 * {@link Page} is returned.
	 *
	 * @param example must not be {@literal null}.
	 * @param pageable can be {@literal null}.
	 * @return a {@link Page} of entities matching the given {@link Example}.
	 */
	<S extends T> Page<S> findAll(Example<S> example, Pageable pageable);

	/**
	 * Returns the number of instances matching the given {@link Example}.
	 *
	 * @param example the {@link Example} to count instances for. Must not be {@literal null}.
	 * @return the number of instances matching the {@link Example}.
	 */
	<S extends T> long count(Example<S> example);

	/**
	 * Checks whether the data store contains elements that match the given {@link Example}.
	 *
	 * @param example the {@link Example} to use for the existence check. Must not be {@literal null}.
	 * @return {@literal true} if the data store contains elements that match the given {@link Example}.
	 */
	<S extends T> boolean exists(Example<S> example);
}

使用案例:

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

public interface UserRepository extends JpaRepository<User, Long> {

}

5.测试用例


import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdataDemoApplicationTests {

    @Autowired
    private UserRepository userRepository;

    @Test
    public void test1() {
        User user = User.builder()
                .name("gouzi")
                .age(25)
                .status(UserStatus.LEVEL1)
                .build();
        userRepository.save(user);
    }

    @Test
    public void test2() {
        //
        userRepository.findAllByName("Tom").forEach(System.out::println);
    }

}

6.自定义持久化语句

6.1 方法名方式

public interface UserRepository extends Repository<User, Long> {

  long countByLastname(String lastname);

  long deleteByLastname(String lastname);

  List<User> removeByLastname(String lastname);

  List<User> findByLastname(String lastname);

  User findByEmailAddress(String emailAddress);
  User findByEmailAddress(EmailAddress emailAddress);

  User getByEmailAddress(EmailAddress emailAddress);                    

  @Nullable
  User findByEmailAddress(@Nullable EmailAddress emailAdress);          

  Optional<User> findOptionalByEmailAddress(EmailAddress emailAddress);

  List<User> findByLastname(String lastname);

  User findByEmailAddress(String emailAddress);

  List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}

拓展:
https://docs.spring.io/spring-data/jpa/docs/2.1.6.RELEASE/reference/html/#jpa.query-methods.query-creation#Table 3. Supported keywords inside method names

关键字案例含义
AndfindByLastnameAndFirstname… where x.lastname = ?1 and x.firstname = ?2
OrfindByLastnameOrFirstname… where x.lastname = ?1 or x.firstname = ?2
Is,EqualsfindByFirstname,findByFirstnameIs,findByFirstnameEquals… where x.firstname = ?1
BetweenfindByStartDateBetween… where x.startDate between ?1 and ?2
LessThanfindByAgeLessThan… where x.age < ?1
LessThanEqualfindByAgeLessThanEqual… where x.age <= ?1
GreaterThanfindByAgeGreaterThan… where x.age > ?1
GreaterThanEqualfindByAgeGreaterThanEqual… where x.age >= ?1
AfterfindByStartDateAfter… where x.startDate > ?1
BeforefindByStartDateBefore… where x.startDate < ?1
IsNullfindByAgeIsNull… where x.age is null
IsNotNull,NotNullfindByAge(Is)NotNull… where x.age not null
LikefindByFirstnameLike… where x.firstname like ?1
NotLikefindByFirstnameNotLike… where x.firstname not like ?1
StartingWithfindByFirstnameStartingWith… where x.firstname like ?1 (parameter bound with appended %)
EndingWithfindByFirstnameEndingWith… where x.firstname like ?1 (parameter bound with prepended %)
ContainingfindByFirstnameContaining… where x.firstname like ?1 (parameter bound wrapped in %)
OrderByfindByAgeOrderByLastnameDesc… where x.age = ?1 order by x.lastname desc
NotfindByLastnameNot… where x.lastname <> ?1
InfindByAgeIn(Collection ages)… where x.age in ?1
NotInfindByAgeNotIn(Collection ages)… where x.age not in ?1
TruefindByActiveTrue()… where x.active = true
FalsefindByActiveFalse()… where x.active = false
IgnoreCasefindByFirstnameIgnoreCase… where UPPER(x.firstame) = UPPER(?1)

6.2 编写SQL

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.emailAddress = ?1")
  User findByEmailAddress(String emailAddress);

  @Query("select u from User u where u.firstname like %?1")
  List<User> findByFirstnameEndsWith(String firstname);

  @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
  User findByEmailAddress(String emailAddress);

  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);

  @Query("select u from User u where u.lastname like ?1%")
  List<User> findByAndSort(String lastname, Sort sort);

  @Query("select u.id, LENGTH(u.firstname) as fn_len from User u where u.lastname like ?1%")
  List<Object[]> findByAsArrayAndSort(String lastname, Sort sort);

  @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
  User findByLastnameOrFirstname(@Param("lastname") String lastname,
                                 @Param("firstname") String firstname);

  @Query("select u from #{#entityName} u where u.lastname = ?1")
  List<User> findByLastname(String lastname);


  @Modifying
  @Query("delete from User u where user.role.id = ?1")
  void deleteInBulkByRoleId(long roleId);

  @QueryHints(value = { @QueryHint(name = "name", value = "value")},
              forCounting = false)
  Page<User> findByLastname(String lastname, Pageable pageable);

  @Override
  @Transactional(timeout = 10)
  public List<User> findAll();

  @Modifying
  @Transactional
  @Query("delete from User u where u.active = false")
  void deleteInactiveUsers();

  // Plain query method
  @Lock(LockModeType.READ)
  List<User> findByLastname(String lastname);

  // Redeclaration of a CRUD method
  @Lock(LockModeType.READ);
  List<User> findAll();

附录

  • https://docs.spring.io/spring-data/jpa/docs/2.1.6.RELEASE/reference/html/
  • https://mp.weixin.qq.com/s/Uw3wkiqD16av3tVW-yiTDQ

相关文章:

  • 心与心的交流
  • SimpleDateFormat 线程不安全案例
  • BPEL和JAVA(一篇不错的BPEL入门)
  • 关于 BlockingQueue 的一些认识及资料汇总
  • 欣闻我班上的学生林健在Image Cup比赛中取得好成绩
  • C#.NET常用函数大全
  • Java基本类型简介
  • 动态调用 WebService
  • 关于 ThreadPoolExecutor 的一些资料汇总及个人认识
  • ADO.NET数据操作摘录
  • 线程池ThreadPoolExecutor的拒绝策略
  • 关于 ScheduledThreadPoolExecutor 的一些资料汇总及个人理解
  • 无聊的事情真多
  • 转载一篇关于JNI实践的博客---以及编写自己的native方法
  • 竞标项目,何必这样呢?
  • [译]如何构建服务器端web组件,为何要构建?
  • 【剑指offer】让抽象问题具体化
  • 【跃迁之路】【519天】程序员高效学习方法论探索系列(实验阶段276-2018.07.09)...
  • Android优雅地处理按钮重复点击
  • ECMAScript入门(七)--Module语法
  • express + mock 让前后台并行开发
  • Java反射-动态类加载和重新加载
  • Java-详解HashMap
  • MySQL主从复制读写分离及奇怪的问题
  • Vue官网教程学习过程中值得记录的一些事情
  • 从0到1:PostCSS 插件开发最佳实践
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 第2章 网络文档
  • 工作手记之html2canvas使用概述
  • 区块链共识机制优缺点对比都是什么
  • 使用 Docker 部署 Spring Boot项目
  • 视频flv转mp4最快的几种方法(就是不用格式工厂)
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 1.Ext JS 建立web开发工程
  • 翻译 | The Principles of OOD 面向对象设计原则
  • 组复制官方翻译九、Group Replication Technical Details
  • 昨天1024程序员节,我故意写了个死循环~
  • ​虚拟化系列介绍(十)
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • $.proxy和$.extend
  • (11)MATLAB PCA+SVM 人脸识别
  • (2015)JS ES6 必知的十个 特性
  • (Matalb时序预测)WOA-BP鲸鱼算法优化BP神经网络的多维时序回归预测
  • (二)windows配置JDK环境
  • (附源码)springboot学生选课系统 毕业设计 612555
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • .NET 设计模式初探
  • /etc/fstab 只读无法修改的解决办法
  • @html.ActionLink的几种参数格式
  • [383] 赎金信 js
  • [52PJ] Java面向对象笔记(转自52 1510988116)
  • [autojs]autojs开关按钮的简单使用