Spring Data JPA应用总结

Spring boot data jpa 1.11.8版本

(一)DAO层实现方法最好继承JpaRepository接口,原因有下(忽略源码):

1. 继承关系:JpaRepository-->PagingAndSortRepository-->CrudRepository;

2. CrudRepository 返回Iteralble,JpaRepository返回的是 List,使用起来更方便;

3. JpaRepository增加了 InBatch 删除方法, 实际执行时,后台生成一条sql语句,效率更高,而CrudRepository 接口】是逐条删除,更可笑的是 deleteAll 也是逐条删除;

4. JpaReporsitory增加了 getOne() 方法,该方法返回的是对象引用,当查询的对象不存在时,它的值不是Null。

5. 当数据进行后台分页时,JpaRepository表现的更加优秀:

自定义分布类:

public class _Page<T> implements Serializable{

    public static final Integer PAGE_SIZE = Integer.MAX_VALUE;
    public static final int DIR_ASC = 0;
    public static final int DIR_DESC = 1;
    public static final String DEFAULT_ORDER = "createTime";       //所有类默认按照创建时间排序

    public _Page(Integer currentPage, Integer pageSize){
        init(pageSize,DIR_DESC,DEFAULT_ORDER);
        this.currentPage = currentPage;
        //从0开始第一页
        this.request = new PageRequest(this.currentPage-1, this.limit, this.dir==DIR_DESC?Sort.Direction.DESC:Sort.Direction.ASC,this.order);
    }

    public _Page(Integer currentPage, Integer limit, Integer dir, String order){
        init(limit,dir,order);
        this.currentPage = currentPage;
        this.request = new PageRequest(this.currentPage-1, this.limit, this.dir==DIR_DESC?Sort.Direction.DESC:Sort.Direction.ASC,this.order);
    }

    private Integer currentPage;
    private Long totalCount;
    private List<T> results;
    private int limit;
    private int dir;
    private String order;   //暂时只按照一列排序,所以不用数组
    @JsonIgnore
    private PageRequest request;

    public Integer getCurrentPage() {
        return currentPage;
    }

    public void setCurrentPage(Integer currentPage) {
        this.currentPage = currentPage;
    }

    public Long getTotalCount() {
        return totalCount;
    }

    public void setTotalCount(Long totalCount) {
        this.totalCount = totalCount;
    }

    public List<T> getResults() {
        return results;
    }

    public void setResults(List<T> results) {
        this.results = results;
    }

    public int getLimit() {
        return limit;
    }

    public void setLimit(int limit) {
        this.limit = limit;
    }

    public int getDir() {
        return dir;
    }

    public void setDir(int dir) {
        this.dir = dir;
    }

    public String getOrder() {
        return order;
    }

    public void setOrder(String order) {
        this.order = order;
    }

    public PageRequest getRequest() {
        return request;
    }

    public void setRequest(PageRequest request) {
        this.request = request;
    }

    private void init(Integer limit,Integer dir,String order){
        this.limit = limit == null? PAGE_SIZE:limit;
        this.dir = dir == null?DIR_ASC:dir;
        if(order==null)this.order = DEFAULT_ORDER;
        else{
            try {
                this.getClass().getField(order);
                this.order = order;
            } catch (NoSuchFieldException e) {
                this.order = DEFAULT_ORDER;
            }
        }
    }
}

根据前端传入分页参数进行分页:

import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;

/**
     * 把查询条件封闭成一个对象,根据对象属性内容进行匹配查询
     *
     * @return
     */
    private ExampleMatcher getMatcher() {
        return ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING).withIgnoreNullValues();
    }

public _Page<Center> pageCenter(int currentPage, Integer limit, String name, Boolean enabled) {
        _Page<Center> _page = new _Page<>(currentPage, limit);
        Center center = new Center(name, enabled);
        Example<Center> example = Example.of(center, getMatcher());
        Page<Center> page = centerDao.findAll(example, _page.getRequest());
        _page.setResults(page.getContent());
        _page.setTotalCount(page.getTotalElements());
        return _page;
    }

6. 前端传入一个JSON对象出现反序列化问题:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.Long out of START_OBJECT token

标记实体主键即可:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@Entity

7. 动态查询最佳实践的项目可参照:https://github.com/wenhao/jpa-spec,前面武功尽废:DAO需要继承两个接口即可:

public interface FarmDao extends JpaRepository<Farm,Long>,JpaSpecificationExecutor<Farm>{
    List<Farm> findByAccountAndEnabled(Long account, Boolean enabled);

    @Transactional
    @Modifying
    @Query(value="UPDATE Farm a SET a.enabled=?2 WHERE a.id=?1")
    Integer enabled(Long id, Boolean enabled);
}

8. 创建数据库出现外键约束错误:

Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Unable to execute schema management to JDBC target [alter table jut_feeding_feed add constraint FK_FEEDING_FEEDING_FEED_ID foreign key (feeding_id) references jut_feeding (id)]
	at org.hibernate.tool.schema.internal.TargetDatabaseImpl.accept(TargetDatabaseImpl.java:59) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
	at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlString(SchemaMigratorImpl.java:431) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
	at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applySqlStrings(SchemaMigratorImpl.java:420) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
	at org.hibernate.tool.schema.internal.SchemaMigratorImpl.applyForeignKeys(SchemaMigratorImpl.java:386) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
	at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigrationToTargets(SchemaMigratorImpl.java:214) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
	at org.hibernate.tool.schema.internal.SchemaMigratorImpl.doMigration(SchemaMigratorImpl.java:60) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
	at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:134) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
	at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:101) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
	at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:472) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
	at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]
	at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) ~[hibernate-entitymanager-5.0.12.Final.jar:5.0.12.Final]

查询FK_FEEDING_FEEDING_FEED_ID,发现有重复的外键名称。

猜你喜欢

转载自my.oschina.net/u/930294/blog/1622352