Spring Data JPA has done some research, basically referring to the official Spring Data JPA-Reference Documentation.
IntroductionDependenciesWorking with Spring Data RepositoriesRepositoriesQuery methodsQuery creationNamingStrategyUsing @QueryUsing SortUsing PageableSave methodsDelete methodsWhy use Spring Date JPA
Introduction
Spring Data JPA, Part of the larger Spring Data family, makes it easy to easily implement JPA based repositories. This module deals with enhanced support for JPA based data access layers. It makes it easier to build Spring-powered applications that use data access technologies.
To explain what Spring Data JPA is, we need to talk about it step by step: at the beginning, JAVA needs to access the database through the API provided by various database vendors. Later, JAVA proposed JDBC, and the program can directly use the JDBC specification to connect with each database. Then came the ORM technology, which simplified the persistence of Java objects. Hibernate, TopLink and other ORM frameworks appeared. In JDK1.5, Sun incorporated the advantages of Hibernate, TopLink and other ORM frameworks, and proposed Java persistence specification: JPA;
Hibernate provided the IMPLEMENTATION of JPA in 3.2, other JPA vendors such as OpenJPA, Toplink, etc. Spring works on persistence, developing a series of spring-data-xxx packages, such as: Spring-data-jpa, spring-data-redis, spring-data-mongodb, etc. These are all spring-provided repositories based on JPA and other NOSQL.
http://stackoverflow.com/questions/16148188/spring-data-jpa-versus-jpa-whats-the-difference
Long story short, then, Spring Data JPA provides a definition to implement repositories that is supported under the hood by referencing the JPA specification, using the provider you define.
Spring Data JPA provides a Repository layer implementation based on the JPA specification, but it is up to you to decide which ORM to use. Spring Data JPA can be seen as a higher level of abstraction than the more familiar Hibernate and MyBatis.
Dependencies
Specific steps you can refer to website: [spring – data – jpa/quick – start] (https://spring.io/projects/spring-data-jpa)
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
</dependencies>
Copy the code
To use Spring Data JPA under Spring Boot, you need to introduce:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Copy the code
Working with Spring Data Repositories
Let’s look at a simple example to realize the function of adding, deleting, checking and changing; As we can see from the example, we can use the method name definition to achieve SQL effect:
For example, findByName(String name) = select * from user where name =?
public interface UserCrudRepository extends CrudRepository<User.String>{
User findOne(String userid);
List<User> findByName(String name);
List<User> findByNameAndAgeLessThan(String name, int age);
void deleteByNameAndAgeLessThan(String name, int age);
List<User> findDistinctByName(String name);
List<User> findByNameIgnoreCase(String name);
User findFirstByOrderByUseridDesc();
}
Copy the code
Repositories
Spring Date JPA provides several interfaces:
- Repository: The top-level interface, which is an empty interface designed to unify all Repository types and automatically identify components when scanning.
- CrudRepository: a subinterface to Repository that provides CRUD functionality.
- PagingAndSortingRepository: CrudRepository as part of the interface, adding paging and sorting functions.
- JpaRepository: PagingAndSortingRepository as part of the interface, increased the batch operation, etc.
Xrepositoty is repositoty to JpaRepository, which is repositoty to JpaRepository.
Query methods
Query creation
You can use the findOne and findAll methods in CrudRepository directly:
public interface UserCrudRepository extends CrudRepository<User.String>{
/ * *
* A method that exists in CrudRepository, but can be omitted here
* /
User findOne(String userid);
/ * *
* Query all methods that can not write this method (inherit parent class)
* do not write this method, need to be strong after the query completed:
* List<User> userAfterDel = (List<User>) this.repository.findAll();
*
* Write this method here:
* List<User> userAfterDel = this.repository.findAll();
* /
List<User> findAll();
}
Copy the code
You can also extend the query method in the following format: find… By, read… By the query… By, get… By the count… By:
public interface UserCrudRepository extends CrudRepository<User.String>{
/ * *
* Query by name, not primary key:
* @param name
* @return
* /
List<User> findByName(String name);
List<User> queryByName(String name);
/ * *
* Query by name and age younger than the entry:
* @param name
* @return
* /
List<User> findByNameAndAgeLessThan(String name, int age);
List<User> findDistinctByName(String name);
List<User> findByNameIgnoreCase(String name);
}
Copy the code
If a database field contains a [_] symbol, the Entity class attribute in JAVA cannot contain [_] and must be associated with the @column (name = “”) tag.
If a Property in a JAVA Entity class is named in camel form, it needs to be associated with the @column (name = “”) tag.
NamingStrategy
Address the second problem above: If a Property in a JAVA Entity class has a camel name, it also needs to be associated with the @column (name = “”) tag.
The NamingStrategy interface in JPA (first proposed in Hibernate) implements the table name and column name naming function in the interface, and can complete its own NamingStrategy setting.
For example, we often run into the problem that the table has columns with user_id, user_name… If all attributes in user.java are not attached, then the @column tag should be used to bind database fields:
@Entity
@Table(name = "USER")
@Data
public class User {
@Column(name = "user_id")
@Id
private String userId;
@Column(name = "user_name") // If there are many such fields, it is also a relatively large amount of work
private String userName;
}
Copy the code
With the implementation of NamingStrateg y interface, the function of the hump to underline can be uniformly completed, userId → user_id, userName → user_name;
Spring Boot provides Configure JPA properties, which can be configured directly in application.yml:
spring.jpa.hibernate.naming.physical-strategy = com.example.MyPhysicalNamingStrategy
Copy the code
In Hibernate5, two mapping strategies are provided:
- spring.jpa.hibernate.naming.physical-strategy: Org. Hibernate. Boot. Model. Naming. PhysicalNamingStrategyStandardImpl don’t do any modification, userId – > userId, userId – > userId
- spring.jpa.hibernate.naming.physical-strategy: Org. Springframework. Boot. The orm. Jpa, hibernate. SpringPhysicalNamingStrategy hump changes into the underline, userId – > user_id, configuration, if you don’t do this policy by default
@Entity
@Table(name = "USER")
@Data
public class User {
@Id
private String userId; @column (name = "user_id") is automatically changed to user_id
private String userName; // Automatically convert to user_name
}
Copy the code
There is also a problem. If the column names of the tables in the database are not consistent, for example, some are underlined and some are not, then it will look weird to write the underlined fields in camel case format and the ununderlined fields in all lowercase format when writing Entity.
@Entity
@Table(name = "USER")
@Data
public class User {
@Id
private String userId; // do not use @column (name = "user_id")
private String userName;
private String cardid; // The column name is cardid, with no underline, so it can't be humped here, but it feels weird from the code style
}
Copy the code
If you have more specific requirements, such as all tables or fields in the database with fixed format prefix, CSC_USER table, CSC_USER_ID, CSC_USER_NAME, you can implement the NamingStrategy interface (if Spring Boot is used, You need to implement the PhysicalNamingStrategy interface) to add the prefix name.
Using @Query
Bind SQL statements using the @Query Annotation (if it looks more intuitive) :
public interface UserCrudRepository extends CrudRepository<User.String>{
//@Query("select u from User u where u.name = ?1")
//@Query("select u from User u where 1=1 and u.name = ?1")
//@Query("select u.userid from User u where 1=1 and u.name = ?1")
//@Query(value="select * from User u where u.name = ?1", nativeQuery = true)
List<User> findByName(String name);
}
Copy the code
Use the @param Annotation to bind the name in the parameter to the name in the query:
public interface UserCrudRepository extends CrudRepository<User.String>{
@Query("select u from User u where u.name = :name and u.gender = :gender")
List<User> findUsersByNameAndGender(@Param("name")String name , @Param("gender")String gender);
}
Copy the code
Using Sort
public interface UserCrudRepository extends CrudRepository<User.String>{
List<User> findByOrderByUseridDesc(a); // In reverse order by Userid
}
Copy the code
Also can inherit PagingAndSortingRepository, use the Sort Sort:
public interface UserPageRepository extends PagingAndSortingRepository<User.String> {
List<User> findAll(Sort sort);
}
Copy the code
Using Pageable
Need extends JpaRepository PagingAndSortingRepository or more advanced.
public class UserPageRepositoryTest {
@Test
public void findPageable() throws Exception {
Page<User> usersPageOne = this.repository.findAll(new PageRequest(0.2));
//1.PageRequest(int page, int size)
//2. Page starts from 0
assertThat(usersPageOne.getContent().size()).isEqualTo(2);
assertThat(usersPageOne.getContent().get(0).getUserId()).isEqualTo("1");
assertThat(usersPageOne.hasPrevious()).isEqualTo(false); // Check if there is a previous page
Page<User> usersPageTwo = this.repository.findAll(usersPageOne.nextPageable()); // Query the next page
assertThat(usersPageTwo.getContent().size()).isEqualTo(2);
assertThat(usersPageTwo.getContent().get(0).getUserId()).isEqualTo("3");
}
}
Copy the code
You can also use the keyword [first] or [top] to obtain the first N items of the result set.
public interface UserCrudRepository extends CrudRepository<User.String>{
User findFirstByOrderByUseridDesc(a);
User findFirstByGenderOrderByUseridDesc(String gender);
}
Copy the code
Save methods
To save an Entity, use crudRepository.save (…) Methods, including Insert and Update.
Delete methods
Delete (), deleteAll(), deleteBy… You can also use the @query tag.
In the JpaRepository interface, the deleteInBatch() method is provided: Deletes the given entities in a batch which means it will create a single {@link Query}.
Why use Spring Date JPA
It can be seen that Compared with Hibernate and MyBatis, Spring Data JPA is more concise in coding and reduces Boilerplate Code.
In fact, the query of transactional micro-service application is usually only detailed query or simple list query, while the real complex query or data analysis should usually be another application or full-text search or ODS/DW, and synchronize data from transactional micro-service, and this part is to go through MyBatis or NOSQL.
Feign does not address the same issues as Spring Data Repository, but the implementation philosophy is the same, with interfaces and coCs to minimize Rest calls to Boilerplate Code.
@FeignClient(url = "https://api.github.com")
interface GitHubClient {
@RequestMapping(method = RequestMethod.GET, value = "/repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@RequestParam("owner") String owner, @RequestParam("repo") String repo);
}
Copy the code
Uncle will point code | article “original”