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,发现有重复的外键名称。