JPA is the abbreviation of Java Persistence API and an ORM specification officially proposed!
JPA specifications are all in the package path: javax persistence.* For example, @ Entity, @ Id and @ Transient are all in this path. These are also some conventional annotations of ORM commonly used in the market.
Spring Data JPA is a JPA framework developed by spring based on Hibernate. It can greatly simplify the writing method of JPA, and realize the access and operation of data almost without writing specific code. In addition to CRUD, it also includes some common functions such as paging and sorting.
pom. Adding dependencies to XML
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency>
application.properties configuration
spring.datasource.url=jdbc:mysql://localhost:3306/rumenz_springboot spring.datasource.username=root spring.datasource.password=root1234 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.hibernate.ddl-auto=update spring.sql.init.mode=always spring.sql.init.schema-locations=classpath:/ddl/user-book.sql spring.sql.init.data-locations=classpath:/ddl/user-book-data.sql
spring. jpa. hibernate. Whether DDL auto updates the database according to the entity class has four attribute values
Attribute value | effect |
---|---|
create | Every time you load hibernate, you will delete the last generated table, and then regenerate the new table according to your model class. Even if there is no change twice, you should do so. This is an important reason for the loss of database table data. |
create-drop | Each time hibernate is loaded, the table is generated according to the model class, but the table is automatically deleted as soon as sessionFactory is closed. |
update | The most commonly used attribute. When hibernate is loaded for the first time, the table structure will be automatically established according to the model class (provided that the database is established first). When hibernate is loaded later, the table structure will be automatically updated according to the model class. Even if the table structure is changed, the rows in the table still exist and the previous rows will not be deleted. It should be noted that when deployed to the server, the table structure will not be established immediately. It will not be established until the application runs for the first time. |
validate | Every time hibernate is loaded, verify that the database table structure is created. It will only be compared with the tables in the database. No new table will be created, but new values will be inserted. |
spring. sql. init. Whether mode uses SQL file to initialize the database has three values
Attribute value | effect |
---|---|
ALWAYS | Always initialize the database. |
EMBEDDED | Initialize only the embedded database. |
NEVER | Never initialize the database. |
- spring. sql. init. Schema locations specifies the SQL file for creating tables
- spring. sql. init. Data locations specifies the data SQL file
Create entity class
User.java @Getter @Setter @Builder @AllArgsConstructor @Entity //jpa required @DynamicInsert //Fill default @DynamicUpdate //Fill default @Table(name = "user") //jpa required @NoArgsConstructor public class User { @Id //jpa required @GeneratedValue(strategy = GenerationType.IDENTITY) //jpa required private Integer id; private String name; private String domain; @Column(name = "age",columnDefinition = "tinyint default 0") private Integer age; }
@GeneratedValue(strategy = GenerationType.IDENTITY) has the following types
- TABLE: use a specific database TABLE to save the primary key.
- SEQUENCE: generate the primary key according to the SEQUENCE of the underlying database, provided that the database supports the SEQUENCE.
- IDENTITY: the primary key is automatically generated by the database (mainly automatic growth type)
- AUTO: the primary key is controlled by the program.
Create a repository
The data persistence layer is responsible for accessing the database. The methods declared here generally do not need to be implemented. SQL statements can be automatically generated as long as they comply with the specifications of Jpa.
package com.rumenz.lession15.controller.repository; import com.rumenz.lession15.controller.entity.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.stereotype.Repository; import java.util.List; import java.util.Optional; /** * @className: UserRepository * @description: TODO Class description * @author: Entry station rumenz com * @date: 2021/12/14 **/ @Repository public interface UserRepository extends PagingAndSortingRepository<User,Integer> { Optional<User> findById(Integer id); List<User> findDistinctUserByName(String name); Integer countUserByName(String name); List<User> readDistinctByName(String name); Page<User> findAllByName(String name, Pageable pageable); }
Jpa can generate corresponding sql statements through the interface name, such as find By,read... By,query... By,count... By, And get By . These methods can include other expressions, such as setting the Distinct flag on the query to be created. The first by is used as a separator to indicate the beginning of the condition. Then, various conditions of entity attributes are defined And connected with And Or. For example:
interface RumenzRepository extends JpaRepository<Rumenz, Long> { List<Rumenz> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname); // Enable the distinct flag for queries List<Rumenz> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname); List<Rumenz> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname); // Enable ignore case for individual attributes List<Rumenz> findByLastnameIgnoreCase(String lastname); // Enable ignore case for all attributes List<Rumenz> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname); // Enable static Order by for queries List<Rumenz> findByLastnameOrderByFirstnameAsc(String lastname); List<Rumenz> findByLastnameOrderByFirstnameDesc(String lastname); }
Give some examples
keyword | Method example | JPQL snippet |
---|---|---|
And | findByLastnameAndFirstname | ... where x.lastname = ?1 and x.firstname = ?2 |
Or | findByLastnameOrFirstname | ... where x.lastname = ?1 or x.firstname = ?2 |
Is, Equals | 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 |
IsNull, Null | findByAge(Is)Null | ... 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 ages) | ... 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) |
There are three types of repositories
JpaRepository inherits pagingandsortingreposition, and pagingandsortingreposition inherits CrudRepository.
- CrudRepository provides CRUD functions
- Pagingandsorting repository provides paging and sorting capabilities
- JPA repository provides JPA related methods, such as refreshing persistent data, batch deletion, etc.
service
The business logic layer is responsible for calling the Repository to process data and complete the business.
package com.rumenz.lession15.controller.service; import com.rumenz.lession15.controller.entity.User; import org.springframework.data.domain.Page; import java.util.List; /** * @className: UserService * @description: TODO Class description * @author: Entry station rumenz com * @date: 2021/12/14 **/ public interface UserService { Integer save(User user); User get(Integer id); List<User> listByName(String name); Integer countByName(String name); List<User> readDistinctByName(String name); Page<User> listByNamePage(String name, Integer page, Integer pageSize); } //Implementation class package com.rumenz.lession15.controller.service.lmpl; import com.rumenz.lession15.controller.entity.User; import com.rumenz.lession15.controller.repository.UserRepository; import com.rumenz.lession15.controller.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import java.util.List; import java.util.Optional; /** * @className: UserServiceImpl * @description: TODO Class description * @author: Entry station rumenz com * @date: 2021/12/14 **/ @Service public class UserServiceImpl implements UserService { @Autowired UserRepository userRepository; @Override public Integer save(User user) { User save = userRepository.save(user); return save.getId(); } @Override public User get(Integer id) { Optional<User> opt = userRepository.findById(id); return opt.isPresent()?opt.get():null; } @Override public List<User> listByName(String name) { List<User> res = userRepository.findDistinctUserByName(name); return res; } @Override public Integer countByName(String name) { return userRepository.countUserByName(name); } @Override public List<User> readDistinctByName(String name) { return userRepository.readDistinctByName(name); } @Override public Page<User> listByNamePage(String name, Integer page, Integer pageSize) { Sort sort = Sort.by("id").descending(); Pageable pageable= PageRequest.of(page-1, pageSize, sort); Page<User> res = userRepository.findAllByName(name, pageable); return res; } }
Controller
The front-end controller is responsible for receiving the front-end request, calling service and returning data.
package com.rumenz.lession15.controller; import com.rumenz.lession15.controller.entity.User; import com.rumenz.lession15.controller.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; /** * @className: RumenzController * @description: TODO Class description * @author: Entry station rumenz com * @date: 2021/12/14 **/ @RestController @RequestMapping("/rumenz") public class RumenzController { @Autowired UserService userService; //Save data //If the data with id=1 does not exist, add it //If the data with id=1 exists, it will be updated @RequestMapping("/save") public String save(){ User user=User.builder().id(1).name("Entry station 123").domain("https://rumenz.com").build(); Integer save = userService.save(user); return save.toString(); } //Query data by id @GetMapping("/get") public User get(@RequestParam("id") Integer id){ return userService.get(id); } //Band query condition @GetMapping("/listByName") public List<User> get(@RequestParam("name") String name){ return userService.listByName(name); } //Query qualified quantity by criteria @GetMapping("/countByName") public Integer countByName(@RequestParam("name") String name){ return userService.countByName(name); } //Band query condition @GetMapping("/readDistinctByName") public List<User> readDistinctByName(@RequestParam("name") String name){ return userService.readDistinctByName(name); } //Paging query //Band query condition @GetMapping("/listByNamePage") public Page<User> listByNamePage(@RequestParam("name") String name, @RequestParam("page") Integer page, @RequestParam("pageSize") Integer pageSize){ return userService.listByNamePage(name,page,pageSize); } }
Source code address of this summary: