Spring boot data jpa 1.11.8版本前端
(一)DAO層實現方法最好繼承JpaRepository接口,緣由有下(忽略源碼):java
1. 繼承關係:JpaRepository-->PagingAndSortRepository-->CrudRepository;git
2. CrudRepository 返回Iteralble,JpaRepository返回的是 List,使用起來更方便;github
3. JpaRepository增長了 InBatch 刪除方法, 實際執行時,後臺生成一條sql語句,效率更高,而CrudRepository 接口】是逐條刪除,更好笑的是 deleteAll 也是逐條刪除;spring
4. JpaReporsitory增長了 getOne() 方法,該方法返回的是對象引用,當查詢的對象不存在時,它的值不是Null。sql
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; } } } }
根據前端傳入分頁參數進行分頁:app
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對象出現反序列化問題:dom
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,發現有重複的外鍵名稱。