Introduction to SpringData

The last time I learned SpringBoot, the tutorial already covered a bit of SpringData JPA. At that time, it was the first time to see it, and I thought it was not a big deal, just encapsulating Hibernate’s API.

Then I saw SpringData’s tutorials on MOOCs. So I went in and studied.

Tutorial address: www.imooc.com/learn/821 source download address: img.mukewang.com/down/58e60b…

SpringData is introduced in the tutorial with the raw JDBC and Spring JDBC Template.

The amount of code required to write the original JDBC and Spring JDBC Template is quite large, so we have a framework like SpringData.

1.1 introduction to SpringDataJPA

SpringData JPA is just a sub-module of SpringData

JPA is a standard set of interfaces, and Hibernate is an implementation of JPA

The default underlying implementation of SpringData JPA is to use Hibernate

The first interface for SpringDataJPA is Repository, which is a markup interface. As long as our interface implements this interface, we are using SpringDataJPA.

Once we implement this interface, we can use “naming by method” to query. I thought he was amazing when I first met him.

1.2 Project Configuration

  1. Add related dependencies in pom.xml
  2. Configure the corresponding properties in the YML or Properties file
  3. Create entity and Repository tests

Reference Resources:

  • Blog.csdn.net/pdw2009/art…
  • Blog.csdn.net/w_x_z_/arti…

Example:

For example: define the following method, which can be used outside.


Employee findByName(String name);

Copy the code

That is, the above method will be parsed into an SQL statement: select * from Employee where name =?

Do not feel very convenient !!!!

If it is a simple operation, you can define such a method directly and use it. Very good indeed.

I don’t know how much better than Mytais. Mybatis also needs to write a mapping file, specifically to write a SQL statement.

In addition, creating an entity automatically creates a database table for us, and modifying the entity field also modifies the database table. Immediately feel very easy to use.


/** * employee: first develop entity class ===> automatically generate table */
@Entity
public class Employee {

    private Integer id;

    private String name;

    private Integer age;

    @GeneratedValue
    @Id
    public Integer getId(a) {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Column(length = 20)
    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge(a) {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age; }}Copy the code

Of course, there are drawbacks to using the method name above:

  • 1) Method names are longer: conventions are larger than configurations
  • 2) For some complex queries, it is difficult to implement

Such as:


    // where name like ? % and age 
      
    public List<Employee> findByNameStartingWithAndAgeLessThan(String name, Integer age);

    // where name like %? and age <?
    public List<Employee> findByNameEndingWithAndAgeLessThan(String name, Integer age);

    // where name in (? ,? ...). or age 
      
    public List<Employee> findByNameInOrAgeLessThan(List<String> names, Integer age);

    // where name in (? ,? ...). and age 
      
    public List<Employee> findByNameInAndAgeLessThan(List<String> names, Integer age);


Copy the code

Therefore, it is much easier to write SQL statements in this case.


    @Query("select o from Employee o where id=(select max(id) from Employee t1)")
    public Employee getEmployeeByMaxId(a);

    @Query("select o from Employee o where o.name=?1 and o.age=?2")
    public List<Employee> queryParams1(String name, Integer age);

    @Query("select o from Employee o where o.name=:name and o.age=:age")
    public List<Employee> queryParams2(@Param("name")String name, @Param("age")Integer age);

    @Query("select o from Employee o where o.name like %?1%")
    public List<Employee> queryLike1(String name);

    @Query("select o from Employee o where o.name like %:name%")
    public List<Employee> queryLike2(@Param("name")String name);

    @Query(nativeQuery = true, value = "select count(1) from employee")
    public long getCount(a);


Copy the code

Hibernate is an HQL/JPQL statement. But it’s much simpler to use than Mybatis.

To Modify data, add the Modify annotation and Modify data only under transaction management


    @Modifying
    @Query("update Employee o set o.age = :age where o.id = :id")
    public void update(@Param("id")Integer id, @Param("age")Integer age);

Copy the code

1.3Repository subclass interface

Implementation of the CURDRepository interface:

Sorting, paging interface:

Interface for adding filter conditions:

JPA interface:

JpaRepository inherit PagingAndSortingRepository PagingAndSortingRepository inherit CrudRepository again, that is our custom interface as long as inherit JpaRepository at ordinary times, It’s like adding, deleting, searching, paging, and so on.

JPQL foundation #

JPQL is a JPA query language. I thought it was the same as HQL. There are two concepts. But they’re pretty much the same.

JPA corresponds to JPQL and Hibernate corresponds to HQL. Both are object-oriented query languages.

2.1 Criteria query ##

There’s a lot of stuff going on here.

2.2 Specification Interface usage

In fact, the API of this interface is the same as the Criteria. If you understand the Criteria API, this interface will be used.

2.3 nameQuery note ##

2.4 the query annotation # #

2.5 small summary

www.zhihu.com/question/53…

An answer to the introduction of Zhihu:

Basic add, delete, change, and call stored procedures are handled by Spring Data JPA Repository

Slightly more complex queries or batch operations are handled using the QueryDSL or Spring Data Specification apis

Very, very complex query operations can be handled using Spring Data JPA Repository annotations to define native SQL

Three, need to pay attention to the place

3.1 Annotations are written on the GET method

At first I thought annotations were written on attributes, but I encountered a lot of bugs and few online solutions.

I encountered a Bug that almost couldn’t find the answer in domestic forums:


org.hibernate.property.access.spi.PropertyAccessBuildingException: Could not locate field nor getter method for property named [cn.itheima.web.domain.Customer#cust_user_id]
Copy the code

I didn’t find the right way. I don’t know where I went wrong.

Later, I went to see JPA’s one-to-many and many-to-one blog for reference and felt that I was still right.

It turns out that most posts annotate the get method, while I annotate the properties directly.

The reason for annotating the Get method is that instead of breaking our encapsulation, I annotate the properties directly, which are private. That’s why I made this mistake.

3.2 Cascading.ALL Use this parameter with caution

When saving data, I thought it was most convenient to use casecade.ALL directly, but there were bugs. Then found the answer: http://blog.csdn.net/csujiangyu/article/details/48223641

3.3 @ OneToOne annotations


@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public@interfaceOneToOne {
     Class targetEntity(a) default void.class;
     CascadeType[]cascade()default(a);FetchType fetch(a) default EAGER;
     boolean optional(a) default true;
     String mappedBy(a) default "";
}
Copy the code

1. The targetEntity attribute represents the default associated entity type, which defaults to the currently tagged entity class. 2. The Cascade property represents the cascading style type of the entities associated with this entity one-to-one. The optional attribute indicates whether the associated entity can have null values. The default value is true. If the value is set to false, the entity cannot be null

3.4 @ JoinColumn annotation

@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public@interfaceJoinColumn {
    String name(a) default "";
    String referencedColumnName(a) default "";
    boolean unique(a) default false;
    boolean nullable(a) default true;
    boolean insertable(a) default true;
    booleanupdatabledefaulttrue;
    String columnDefinition(a) default "";
    String table(a) default "";
}
Copy the code

** If name is not set, default name = name of the associated table + “-” + name of the associated table primary key field, in example 3 above, default is “address_id” ** By default, The primary key of the associated entity is usually used as a foreign key, but if you do not want to use the primary key as a foreign key, you need to set the referencedColumnName attribute, for example:


create table address (
    id int(20) not null auto_increament,
    ref_id int(20) notn ull,
    province varchar(50),
    city varchar(50),
    postcode varchar(50),
    detail varchar(50),
    primary key(id)
)

@OneToOne@JoinColumn(name="address_id", referencedColumnName="ref_id")
private AddressEO address;
Copy the code

4. Read more

Later, I used SpringData JPA for a simple project and encountered a lot of problems and related knowledge points that I did not touch. Below, I will give the information searched at that time, the problems encountered and the solutions

4.1 Problems encountered and solutions

The problems encountered by SpringData JPA include:

References:

  • www.cnblogs.com/sevenlin/p/…

  • Blog.csdn.net/qq_35797610…

  • CascadeType JPA Spring understands: It’s better to only use REFRESH in the beginning, and then add MERGER etc when there are problems, otherwise it will be messy at first

    • Blog.sina.com.cn/s/blog_9c2c…
  • One-to-many, many-to-one configuration problems. Annotations are written to GETTER methods, not properties. This will avoid a lot of unnecessary mistakes

    • www.jianshu.com/p/0a2163273…
    • Blog.csdn.net/ABAP_Brave/…
    • Blog.csdn.net/lyg_2012/ar…
    • Blog.sina.com.cn/s/blog_76c4…
    • Blog.csdn.net/mendeliangy…
    • www.jianshu.com/p/5c416a780…
  • Exception handling:

    • Detached entity passed to persist exception:
      • Blog.csdn.net/csujiangyu/…
    • More than a pile of JPA circular reference error HttpMessageNotWritableException:
      • Blog.csdn.net/wangping122…

Five, the summary

In general, SpringData JPA is very convenient for single-table operations, and a bit cumbersome for more complex operations because it returns Object[] and has to be manually encapsulated. Flexibility is low…

If the article has the wrong place welcome to correct, everybody exchanges with each other. Students who are used to reading technical articles on wechat and want to get more Java resources can follow the wechat public account :Java3y