Spring JPA知识点整理

Spring JPA介绍官网:

https://docs.spring.io/spring-data/jpa/docs/2.4.3/reference/html/#repositories.core-concepts

The following table describes the keywords supported for JPA and what a method containing that keyword translates to:

Table 3. Supported keywords inside method names
KeywordSampleJPQL snippet

Distinct

findDistinctByLastnameAndFirstname

select distinct …​ where x.lastname = ?1 and x.firstname = ?2

And

findByLastnameAndFirstname

… where x.lastname = ?1 and x.firstname = ?2

Or

findByLastnameOrFirstname

… where x.lastname = ?1 or x.firstname = ?2

IsEquals

findByFirstname,findByFirstnameIs,findByFirstnameEquals

… where x.firstname = ?1

Between

findByStartDateBetween

… where x.startDate between ?1 and ?2

LessThan

findByAgeLessThan

… where x.age < ?1

LessThanEqual

findByAgeLessThanEqual

… where x.age <= ?1

GreaterThan

findByAgeGreaterThan

… where x.age > ?1

GreaterThanEqual

findByAgeGreaterThanEqual

… where x.age >= ?1

After

findByStartDateAfter

… where x.startDate > ?1

Before

findByStartDateBefore

… where x.startDate < ?1

IsNullNull

findByAge(Is)Null

… where x.age is null

IsNotNullNotNull

findByAge(Is)NotNull

… where x.age not null

Like

findByFirstnameLike

… where x.firstname like ?1

NotLike

findByFirstnameNotLike

… where x.firstname not like ?1

StartingWith

findByFirstnameStartingWith

… where x.firstname like ?1 (parameter bound with appended %)

EndingWith

findByFirstnameEndingWith

… where x.firstname like ?1 (parameter bound with prepended %)

Containing

findByFirstnameContaining

… where x.firstname like ?1 (parameter bound wrapped in %)

OrderBy

findByAgeOrderByLastnameDesc

… where x.age = ?1 order by x.lastname desc

Not

findByLastnameNot

… where x.lastname <> ?1

In

findByAgeIn(Collection<Age> ages)

… where x.age in ?1

NotIn

findByAgeNotIn(Collection<Age> ages)

… where x.age not in ?1

True

findByActiveTrue()

… where x.active = true

False

findByActiveFalse()

… where x.active = false

IgnoreCase

findByFirstnameIgnoreCase

… where UPPER(x.firstname) = UPPER(?1)

 

也支持xml定义:

<named-query name="User.findByLastname"> <query>select u from User u where u.lastname = ?1</query> </named-query>

通过自定义Query:

public interface UserRepository extends JpaRepository<User, Long> {

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

 

Like:

public interface UserRepository extends JpaRepository<User, Long> {

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

使用Native SQL 也就是原生的SQL语句查询:

public interface UserRepository extends JpaRepository<User, Long> {

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

一次性带分页统计(一般不需要,直接用默认带分页的查询方法就可以):

public interface UserRepository extends JpaRepository<User, Long> {

  @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);
}

排序:

public interface UserRepository extends JpaRepository<User, Long> {

  @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);
}

repo.findByAndSort("lannister", Sort.by("firstname"));                
repo.findByAndSort("stark", Sort.by("LENGTH(firstname)"));            
repo.findByAndSort("targaryen", JpaSort.unsafe("LENGTH(firstname)")); 
repo.findByAsArrayAndSort("bolton", Sort.by("fn_len"));               

绑定参数名形式:

public interface UserRepository extends JpaRepository<User, Long> {

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

使用SpEL 表达式,可以使用动态表名,实际上是通过Domain对象对应的Entity指定表名或对象名所决定的,如果做分表应当是有用,比如同样的表结构,按年分表的查询

具体见:https://docs.spring.io/spring-data/jpa/docs/2.4.3/reference/html/#jpa.query.spel-expressions

@Entity
public class User {

  @Id
  @GeneratedValue
  Long id;

  String lastname;
}

public interface UserRepository extends JpaRepository<User,Long> {

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

更新指定字段,仅更新一个表的个别字段时可以使用:

@Modifying
@Query("update User u set u.firstname = ?1 where u.lastname = ?2")
int setFixedFirstnameFor(String firstname, String lastname);

删除语句,按某些特殊字段删除时使用:

interface UserRepository extends Repository<User, Long> {

  void deleteByRoleId(long roleId);

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

 自定义BaseRepository的方法:

https://docs.spring.io/spring-data/jpa/docs/2.4.3/reference/html/#repositories.customize-base-repository

 (1) 自定义基础类,需要有构造函数:

class MyRepositoryImpl<T, ID>
  extends SimpleJpaRepository<T, ID> {

  private final EntityManager entityManager;

  MyRepositoryImpl(JpaEntityInformation entityInformation,
                          EntityManager entityManager) {
    super(entityInformation, entityManager);

    // Keep the EntityManager around to used from the newly introduced methods.
    this.entityManager = entityManager;
  }

  @Transactional
  public <S extends T> S save(S entity) {
    // implementation goes here
  }
}

 (2) 在SpringBoot的配置类或启动程序中增加声明

@Configuration
@EnableJpaRepositories(repositoryBaseClass = MyRepositoryImpl.class)
class ApplicationConfiguration { … }

或者用xml形式:

<repositories base-package="com.acme.repository"
     base-class="….MyRepositoryImpl" />

事件的监控,可以对增删改事件进行监控和后序处理,应该可以用来做内容保存后的创建索引等逻辑:

class AnAggregateRoot {

    @DomainEvents 
    Collection<Object> domainEvents() {
        // … return events you want to get published here
    }

    @AfterDomainEventPublication 
    void callbackMethod() {
       // … potentially clean up domain events list
    }
}

The methods are called every time one of a Spring Data repository’s save(…)saveAll(…)delete(…) or deleteAll(…) methods are called.

用法参考:https://blog.csdn.net/f4761/article/details/84622317

 

给实体对象加上@DynamicUpdate,提高更新效率,也就是指更改变化的字段,能够提高一些效率

 

Spring JPA动态表:

import org.hibernate.EmptyInterceptor;

public class JPAInterceptor extends EmptyInterceptor{
    @Override
    public String onPrepareStatement(String sql) {
        System.out.println(sql);
        return super.onPrepareStatement(sql);
    }
}

 实现该接口,配置:

spring.jpa.properties.hibernate.ejb.interceptor=xxxx.JPAInterceptor
这样就能拦截jpa执行sql,然后对其中表名进行替换了,可在Onxxx方法利用ThreadLocal设定Entity标记判断是否对sql进行处理,或者获取Entity中的属性取值然后按该取值进行分表。
参考:https://my.oschina.net/u/1053238/blog/1611773


posted on 2021-01-19 09:27  webjlwang  阅读(254)  评论(0编辑  收藏  举报

导航