JPA

Jpa is a set of Spring Date specifications derived from orM ideas

Orm idea: each entity class corresponds to a database table, operating on the entity class is equivalent to operating on the database, mapping the entity class to the database table

Orm thought derived from Hibernate framework, is the implementation of ORM thought, but in addition to Hibernate framework, there are many frameworks to implement ORM thought, repeated learning will consume a lot of time, so the emergence of JPA, JPA is an integration of ORM thought framework, defines a specification, Reduce the cost of learning.

Jpa environment setup

  • Import the initiator dependencies of JPA
 		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
Copy the code
  • Set jPA parameters in the configuration file
## JPA configuration
The type of database that jPA connects to
spring.jpa.database=MYSQL
## jPA create table strategy
spring.jpa.hibernate.ddl-auto=create-drop
Format output
spring.jackson.serialization.indent_output=true
Table names, fields are lowercase, and delimiters "_" when uppercase letters are present.
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Format the SQL statement in the log
spring.jpa.properties.hibernate.format_sql=true
## Set the debug of the log level to be printed
logging.level.org.hibernate.SQL=debug
## Display SQL statements in logs
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=trace
Copy the code

The core interface of JPA

Repository<T,ID>

Provides queries based on method naming (top-level interface)

public interface BookRepository extends JpaRepository<Book.Integer>, JpaSpecificationExecutor<SecurityProperties.User> {// The jpaRepository interface inherits the CrudRepository interface
    Book findByIdAndBookName(Integer id,String name);// This method will query the table corresponding to the Book by id and bookName
}
Copy the code

Method naming conventions:

  • The method name starts with findBy
  • Followed by the class name of the entity class (can be omitted)
  • Follow the criteria for the query
  • Multiple conditions are connected by And

Once the specification is implemented, JPA implements the query method by mapping conditions based on the order of parameters

Provides queries and updates based on @Query annotations

@Query("from Book where bookName=?" )
    List<Book> queryMyBook(String bookName);
Copy the code

The default value in this annotation is an HQL statement. According to the object query, if you want to write an SQL statement, you need to add the ==nativeQuery=true= attribute to indicate that the value is a native SQL statement

@Query("update Book set name=? where id=?" )
@Modifying// indicates that this is an update operation and is used with squry to implement update
void updateBook(String name,Integer id);
Copy the code

CrudRepository interface

This interface inherits the JpaRepository<T,ID> interface and performs CRUD operations.

public interface CrudRepository<T.ID> extends Repository<T.ID> {
    <S extends T> S save(S var1);Update if there is data in the table, insert if there is no data
    <S extends T> Iterable<S> saveAll(Iterable<S> var1);
    Optional<T> findById(ID var1);
    boolean existsById(ID var1);
    Iterable<T> findAll(a);
    Iterable<T> findAllById(Iterable<ID> var1);
    long count(a);
    void deleteById(ID var1);
    void delete(T var1);
    void deleteAll(Iterable<? extends T> var1);
    void deleteAll(a);
}
Copy the code

The add, delete and change methods here are all added to transaction management


PagingAndSortingRepository interface < T, ID >

This interface inherits the CrudRepository interface, adding some paging and sorting operations

public interface PagingAndSortingRepository<T.ID> extends CrudRepository<T.ID> {
    Iterable<T> findAll(Sort var1);/ / sorting
    Page<T> findAll(Pageable var1);/ / paging
}
Copy the code

The two methods in this interface can only sort and paginate all data, and no conditional sort and pagination methods are defined

  • Sorting method

Direction: Enumeration classes for various sorts

Order object: collation

// Order defines collation rules
Order order=new Order(Direction.Desc,"id");// Descending by ID
Copy the code

Sort object: An object that encapsulates collation rules

Sort sort=newSort(order..) ;// Multiple collations can be added
Class obj=(Class)**RepositoryPagingAndSorting.findAll(sort);// Returns an Iterable
      
        type that requires a strong twist
      
Copy the code
  • Paging method

Pageable: encapsulates the Pageable parameters, the current page, and the number of items to display on each page, starting at 0

Pageable pageable=new PageRequest(0.2);//PageRequest to specify two parameters
Page<Class> page = **RepositoryPagingAndSorting.findAll(pageable);
Copy the code

JpaRepository < T, ID > interface

This method inherited PagingAndSortingRepository < T, ID > interface, the main method in the parent class interface adapter, the return value of I also added some new abstract methods

Such as:

// This is the findAll method of JpaRepository that returns a list
@Override
List<T> findAll(Sort sort);

/ / this is PagingAndSortingRepository the.findall method, the return value is the Iterable < T >
Iterable<T> findAll(Sort var1);
Copy the code

JpaSpecificationExecutor interface

This interface provides multi-conditional queries and includes paging and sorting in conditional queries

== Note == : This interface is a top-level interface and does not have any parent interface

public interface JpaSpecificationExecutor<T> {
    Optional<T> findOne(@Nullable Specification<T> spec);
	List<T> findAll(@Nullable Specification<T> spec);
	Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);
	List<T> findAll(@Nullable Specification<T> spec, Sort sort);
	long count(@Nullable Specification<T> spec);
}
Copy the code

All methods of this interface accept Specification type parameters

Specification interface defines the connection method of complex query and the construction method of query conditions

public interface Specification<T> extends Serializable {
    static <T> Specification<T> not(@Nullable Specification<T> spec){}
    static <T> Specification<T> where(@Nullable Specification<T> spec) {}
	default Specification<T> and(@Nullable Specification<T> other){}
	default Specification<T> or(@Nullable Specification<T> other) {}
	Predicate toPredicate(Root
       
         root, CriteriaQuery
         query, CriteriaBuilder criteriaBuilder)
       ;
}
Copy the code
  • The first four methods of Specification operate on the entire WHERE expression, which has the same effect as executing the method on the expression as a whole
  • The above four methods are all conditional connection methods, and the last toPredicate method is the construction of query conditions

Root: holds the object of the entity class

CriteriaQuery<? > : Query statement construction

CriteriaBuilder: Construction of query conditional expressions, containing various aggregation functions


Relational mapping between tables

There are three possible relationships between tables: one-to-one, one-to-many, and many-to-many

The foreign key relationships between tables in JPA are not maintained by the database, but by JPA through indexes

There are one-way binding and bidirectional binding between tables. One-way binding can operate on secondary tables from the primary table, while bidirectional binding can operate on each other

One-to-many relationship

  • Two-way one-to-many:

    • The main table

    • public class Book {
          @OneToMany(mappedBy = "book",cascade = CascadeType.PERSIST)
          private List<Author> authorList = new ArrayList<>();
      Copy the code
    • From the table

    • public class Author {
      	@ManyToOne
          @JoinColumn(name = "bookId")
          private Book book;
      Copy the code

The @joinColumn annotation is written to the foreign key to specify the name of the foreign key, and is used with @manytoone

  • Add a one-to-many association

    • The test code

    • @Test
          public void testSave(a){
              / / build the author
              Author author=new Author();
              author.setAuthorName("Zhang");
      
              / / to build the book
              Book book = new Book();
              book.setBookDesc("good!");
              book.setBookName("head first");
              book.setCreatedTime(new Date());
      
              // Build relationships
              book.getAuthorList().add(author);
              author.setBook(book);
              bookRepository.save(book);
          }
      Copy the code

      Add the cascade attribute to book and set it to cascadeType.persist

      • ALL: equals to cascade={PERSIST, MERGE, REMOVE, REFRESH, DETACH}, which means that ALL operations are cascades
      • PERSIST: Sets the Insert operation to cascade
      • MERGE: Sets the update operation to cascade
      • REFRESH: When two updates are performed concurrently, the last one must REFRESH to get the latest data before the update operation can be performed
      • REMOVE: Cascade the DELETE operation
      • DETACH: Delete association, when you have this permission, it will undo all foreign key associations, then you can delete entities with foreign keys

Many-to-many relationships

  • Many to many

    • Table 1

    • public class Book {
          @ManyToMany(cascade = CascadeType.PERSIST)
          @JoinTable(name = "t_book_author",joinColumns = @JoinColumn(name = "book_id"),inverseJoinColumns = @JoinColumn(name = "author_id"))
          @apiModelProperty (" Author of this book ")
          private List<Author> authorList = new ArrayList<>();
      Copy the code
    • Table 2.

    • public class Author {
          @ManyToMany(mappedBy = "authorList")
          @apiModelProperty (" Book by this author ")
          private List<Book> bookList;
      Copy the code

In a many-to-many relationship, the @JoinTable annotation is used to specify the name of the intermediate table and the names of the two foreign keys

  • Name: : creates an intermediate table based on this attribute name
  • JoinColumns: This attribute uses @joinColumn to specify the name of the foreign key corresponding to this ID in the middle table
  • InverseJoinColumns: This attribute uses @joinColumn to specify the name of the foreign key corresponding to the id of table 2 in the middle table

Annotate another table with @manytomany and specify the maintainer of the relationship, mappedBy

  • test

    • / / to create a book
      Book book = new Book();
      book.setBookName("mybook2");
      book.setBookDesc("very good22");
      
      / / create an author
      Author author1=new Author();
      author1.setAuthorName("jack2");
      
      Author author2=new Author();
      author2.setAuthorName("rose2");
      
      // Set the association
      book.getAuthorList().add(author1);
      book.getAuthorList().add(author2);
      
      author1.getBookList().add(book);
      author2.getBookList().add(book);
      
      // Cascade save
      bookRepository.save(book);
      Copy the code
  • == Tread pit diary: ==

    Today in jpa table relationships, more add operation of cascade are going well, until the query operation of the cascade, first met = = LazyInitializationExceptions = = = = no session = = exceptions, this exception is due to the lack of control over the affairs in junit environment, The session is closed when you need to obtain the session, causing noSession exceptions

    Resolve this exception by annotating the method with the @Transactional annotation

    Lombok’s @toString () error is caused by ignoring the ToString () method. Lazy loading triggers loading conditions when the entity class object is used. However, since toString does not use entity classes, it does not trigger lazy loading conditions and calls query methods in an infinite loop on the console until the stack runs out. (Not only does toString use entity classes, but hashCode, Equals, etc.)

    • Problem: Since Lombok’s @data annotation generates toString methods that contain all member attributes by default, our multi-table relationships are lazy-loaded by default, and the primary table’s toString method does not trigger an associative query from the table, so the toString method is repeatedly called until the stack overflows.

    • Solution: Override toString method, do not display entity class collection of associated table

    • Overrides the toString method

      • public class Author {
            private Integer id;
            private String authorName;
            private List<Book> bookList=new ArrayList<>();// Block this member from toString
            
            public String toString(a) {
                    return "Author{" +
                            "id=" + id +
                            ", authorName='" + authorName + '\' ' +
                            '} '; }}public class Book {
            private Integer id;
            private String bookName;
            private String bookDesc;
            private Date createdTime;
            private List<Author> authorList = new ArrayList<>();// Block this member from toString
            
            public String toString(a) {
                    return "Book{" +
                            "id=" + id +
                            ", bookName='" + bookName + '\' ' +
                            ", bookDesc='" + bookDesc + '\' ' +
                            ", createdTime=" + createdTime +
                            '} ';
            }
        Copy the code

    This allows the query operation to work normally