Spring Boot (five): Spring Boot Jpa use

A, Spring Boot Jpa Profile

Jpa (Java Persistence API) is a java sun Crown persistence specification. It provides an object for the java developer / association mapping tool to manage relational data java applications. It appears mainly to simplify the existing persistence ORM technology development and integration, ending now hibernate, toplink, jdo and other ORM frameworks for their own business situation.

Notably, JPA is fully absorbed in the ORM evolved existing framework, an easy to use, stretchable and strong advantages. From the reaction of the current development community point of view, Jpa been a great support and praise, including a spring and EJB development team.

Note: Jpa is a norm, not a product, like Hibernate, TopLink, JDO they are a product, if these products to achieve this Jpa specification, then we can call them Jpa of their products.

Spring ORM based on the Boot Jpa the Spring Framework, the package on the basis of a specification JPA Jpa application framework, developers can use the minimalist and code to enable access to the database operations. It offers including CRUD etc., commonly used functions, and easy to expand! Learn and use Spring Boot Jpa can greatly improve development efficiency.

Second, the basic query

The basic queries can also be divided into two types, one is the Spring Data default has been achieved, one is automatically parsed into SQL queries based on the method.

1, pre-generated method

Spring Boot Jpa previously generated default some basic CRUD methods.

(1) inherited JpaRepository

public interface UserRepository extends JpaRepository<User, Long> {
}

(2) using the default method

@Test
public void testBaseQuery() throws Exception {
	User user=new User();
	userRepository.findAll();
	userRepository.findOne(1l);
	userRepository.save(user);
	userRepository.delete(user);
	userRepository.count();
	userRepository.exists(1l);
	// ...
}

The method will not explain the meaning of the name will be seen

2, custom simple query

Custom simple query is to automatically generate SQL according to the method name, the main grammar

Is findXXBy, readAXXBy, queryXXBy, countXXBy, getXXBy followed by property name:

User findByUserName(String userName);

Also use some add some keywords And, Or

User findByUserNameOrEmail(String username, String email);

Modify, delete, statistics also similar syntax

Long deleteById(Long id);
Long countByUserName(String userName)

System substantially SQL keywords may be used, for example: like, ignoreCase, OrderBy.

List<User> findByEmailLike(String email);
User findByUserNameIgnoreCase(String userName);
List<User> findByUserNameOrderByEmailDesc(String email);

Specific keywords, and generate usage follows sql

Keyword Sample JPQL snippet
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is,Equals 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
IsNull findByAgeIsNull … where x.age is null
IsNotNull,NotNull 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 ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection age) … where x.age not in ?1
TRUE findByActiveTrue () … where x.active = true
FALSE findByActiveFalse () … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

3, complex queries

In the actual development, we need to use tabs, delete selection, even when the query tables, etc. need special methods or custom SQL

4, paging query

Paging query in the actual use is very common, Spring Boot Jpa has helped us achieve paging function, in a query method, the need to pass parameters Pageable, when there are multiple query parameters when Pageable recommended as the last parameter incoming.

Page<User> findALL(Pageable pageable);
Page<User> findByUserName(String userName,Pageable pageable);

Pageable 是 Spring 封装的分页实现类,使用的时候需要传入页数、每页条数和排序规则

@Test
public void testPageQuery() throws Exception {
	int page=1,size=10;
	Sort sort = new Sort(Direction.DESC, "id");
    Pageable pageable = new PageRequest(page, size, sort);
    userRepository.findALL(pageable);
    userRepository.findByUserName("testName", pageable);
}

5、限制查询

有时候我们只需要查询前N个元素,或者支取前一个实体。

User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
List<User> findFirst10ByLastname(String lastname, Sort sort);
List<User> findTop10ByLastname(String lastname, Pageable pageable);

6、自定义sql查询

其实 Spring Data 觉大部分的 SQL 都可以根据方法名定义的方式来实现,但是由于某些原因我们想使用自定义的 SQL 来查询,Spring Data 也是完美支持的;在 SQL 的查询方法上面使用@Query注解,如涉及到删除和修改在需要加上@Modifying也可以根据需要添加@Transactional对事物的支持,查询超时的设置等。

@Modifying
@Query("update User u set u.userName = ?1 where u.id = ?2")
int modifyByIdAndUserId(String  userName, Long id);
	
@Transactional
@Modifying
@Query("delete from User where id = ?1")
void deleteByUserId(Long id);
  
@Transactional(timeout = 10)
@Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);

7、多表查询

多表查询 Spring Boot Jpa 中有两种实现方式,第一种是利用 Hibernate 的级联查询来实现,第二种是创建一个结果集的接口来接收连表查询后的结果,这里主要第二种方式。

首先需要定义一个结果集的接口类。

public interface HotelSummary {

	City getCity();

	String getName();

	Double getAverageRating();

	default Integer getAverageRatingRounded() {
		return getAverageRating() == null ? null : (int) Math.round(getAverageRating());
	}

}

查询的方法返回类型设置为新创建的接口

@Query("select h.city as city, h.name as name, avg(r.rating) as averageRating "
		- "from Hotel h left outer join h.reviews r where h.city = ?1 group by h")
Page<HotelSummary> findByCity(City city, Pageable pageable);

@Query("select h.name as name, avg(r.rating) as averageRating "
		- "from Hotel h left outer join h.reviews r  group by h")
Page<HotelSummary> findByCity(Pageable pageable);

使用

Page<HotelSummary> hotels = this.hotelRepository.findByCity(new PageRequest(0, 10, Direction.ASC, "name"));
for(HotelSummary summay:hotels){
		System.out.println("Name" +summay.getName());
	}

在运行中 Spring 会给接口(HotelSummary)自动生产一个代理类来接收返回的结果,代码汇总使用getxx的形式来获取。

三、多数据源的支持

1、同源数据库的多源支持

日常项目中因为使用的分布式开发模式,不同的服务有不同的数据源,常常需要在一个项目中使用多个数据源,因此需要配置Spring Data Jpa对多数据源的使用,一般分三步:

(1)配置多数据源

(2)不同源的实体类放入不同包路径

(3)声明不同的包路径下使用不同的数据源、事务支持

2、异构数据库多源支持

比如我们的项目中,即需要对 mysql 的支持,也需要对 Mongodb 的查询等 。

实体类声明@Entity关系型数据库支持类型、声明@Document为 Mongodb 支持类型,不同的数据源使用不同的实体就可以了

interface PersonRepository extends Repository<Person, Long> {}

@Entity
public class Person {}

interface UserRepository extends Repository<User, Long> {}

@Document
public class User {}

但是,如果 User 用户既使用 Mysql 也使用 Mongodb 呢,也可以做混合使用

interface JpaPersonRepository extends Repository<Person, Long> {}

interface MongoDBPersonRepository extends Repository<Person, Long> {}

@Entity
@Document
public class Person {}

也可以通过对不同的包路径进行声明,比如 A 包路径下使用 mysql,B 包路径下使用 MongoDB

@EnableJpaRepositories(basePackages = "com.neo.repositories.jpa")
@EnableMongoRepositories(basePackages = "com.neo.repositories.mongo")
interface Configuration { }

四、使用枚举

使用枚举的时候,我们希望数据库中存储的是枚举对应的 String 类型,而不是枚举的索引值,需要在属性上面添加@Enumerated(EnumType.STRING)注解

@Enumerated(EnumType.STRING) 
@Column(nullable = true)
private UserType type;

五、不需要和数据库映射的属性

正常情况下我们在实体类上加入注解@Entity,就会让实体类和表相关连如果其中某个属性我们不需要和数据库来关联只是在展示的时候做计算,只需要加上@Transient属性既可。

@Transient
private String  userName;

 

一杯咖啡,一行代码,是一种境界,也是一种追求!

发布了110 篇原创文章 · 获赞 8 · 访问量 6905

Guess you like

Origin blog.csdn.net/guorui_java/article/details/104241662