JPA官方地址:
JPA语法规则:
JPA框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如 find、findBy、read、readBy、get、getBy,然后对剩下部分进行解析。并且如果方法的最后一个参数是 Sort 或者 Pageable 类型,也会提取相关的信息,以便按规则进行排序或者分页查询。
And — 等价于 SQL 中的 and 关键字,比如 findByUsernameAndPassword(String user, Striang pwd);
Or — 等价于 SQL 中的 or 关键字,比如 findByUsernameOrAddress(String user, String addr);
Between — 等价于 SQL 中的 between 关键字,比如 findBySalaryBetween(int max, int min);
LessThan — 等价于 SQL 中的 “<”,比如 findBySalaryLessThan(int max);
GreaterThan — 等价于 SQL 中的”>”,比如 findBySalaryGreaterThan(int min);
IsNull — 等价于 SQL 中的 “is null”,比如 findByUsernameIsNull();
IsNotNull — 等价于 SQL 中的 “is not null”,比如 findByUsernameIsNotNull();
NotNull — 与 IsNotNull 等价;
Like — 等价于 SQL 中的 “like”,比如 findByUsernameLike(String user);
NotLike — 等价于 SQL 中的 “not like”,比如 findByUsernameNotLike(String user);
OrderBy — 等价于 SQL 中的 “order by”,比如 findByUsernameOrderBySalaryAsc(String user);
Not — 等价于 SQL 中的 “! =”,比如 findByUsernameNot(String user);
In — 等价于 SQL 中的 “in”,比如 findByUsernameIn(Collection userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
NotIn — 等价于 SQL 中的 “not in”,比如 findByUsernameNotIn(Collection userList) ,方法的参数可以是 Collection 类型,也可以是数组或者不定长参数;
Entity - 设定递增列UUID:
@Id
@GenericGenerator(name = "PKUUID", strategy = "uuid2")
@GeneratedValue(generator = "PKUUID")
@Column(length = 36)
protected String id;
在Entity添加1:n 或m:n映射:
示例:
Floor类:
@OneToMany
(fetch =
FetchType.LAZY
,mappedBy =
"floor"
)
private
List<FloorContent>
floorContents
;
FloorContent类:
@ManyToOne
@JoinColumn
(name =
"floor_id"
,foreignKey =
@ForeignKey
(name =
"fk_floor_fc"
))
private
Floor
floor
;
连接查询
方法:
public
interface
FloorContentRepos
extends
JpaRepository<FloorContent,String>{
public
Page<FloorContent>
findByFloor_IdAndIsDeleteOrderByShowIndexAsc
(String floorId,
boolean
b, Pageable pageable);
}
注意:在findBy后面添加要关联的实体类,然后在
实体类后面写上“_”,"_"符号后面是添加关联表的字段而不是本身表的字段。
And+表名字+“_”+表中要查询的字段。
生成关联表
:
不希望生成:
@OneToMany(
mappedBy
=
"a"
)
Like写法:
@Query
(
"SELECT u.username FROM User u WHERE u.username LIKE CONCAT('%',:username,'%')"
)
方式一:
@Query("select a from AccountInfo a where a.accountId = ?1") public AccountInfo findByAccountId(Long accountId);
方式二:
@Query("from AccountInfo a where a.accountId = :id") public AccountInfo findByAccountId(@Param("id")Long accountId);
//使用 @Modifying 将查询标识为修改
@Modifying @Query("update AccountInfo a set a.salary = ?1 where a.salary < ?2") public int increaseSalary(int after, int before);
SpringMVC中JPA(含分页功能)的使用:
@RequestMapping(value = { "list", "" })
public String list(Model model, HttpServletRequest request) {
int page = 0;
int pageSize = 10;
Pageable pager =new PageRequest(page, pageSize);
Page<Employee> employeesPage = manager.getPageEmployee(pager);
model.addAttribute("employees", employeesPage.getContent());
model.addAttribute("resultTotal", employeesPage.getTotalElements());
return "employee/queryEmployee";
}
Demo参考:
(包括注入EntityManagerFactory的方式)
findAll(pageable) 查询:
public Page<Task> getUserTask(Long userId, Map<String, Object> searchParams, int pageNumber, int pageSize,
String sortType) {
PageRequest pageRequest = buildPageRequest(pageNumber, pageSize, sortType);
Specification<Task> spec = buildSpecification(userId, searchParams);
return taskDao.findAll(spec, pageRequest);
}
/**
* 创建分页请求.
*/
private PageRequest buildPageRequest(int pageNumber, int pagzSize, String sortType) {
Sort sort = null;
if ("auto".equals(sortType)) {
sort = new Sort(Direction.DESC, "id");
} else if ("title".equals(sortType)) {
sort = new Sort(Direction.ASC, "title");
}
return new PageRequest(pageNumber - 1, pagzSize, sort);
}
/**
* 创建动态查询条件组合:https://github.com/springside/springside4
*/
private Specification<Task> buildSpecification(Long userId, Map<String, Object> searchParams) {
Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
filters.put("user.id", new SearchFilter("user.id", Operator.EQ, userId));
Specification<Task> spec = DynamicSpecifications.bySearchFilter(filters.values(), Task.class);
return spec;
}
使用传统的EnitityManager来查询单条记录:
@Autowired
private EnitityManager em;
em.createQuery(query).setFirstResult(start).setMaxResults(max).getResultList();
添加查询条件:
使用
Specification<T>或
Criteria<T>:
Criteria<UserInfo> criteria = new Criteria<>();criteria.add(Restrictions.eq("id",10)).add(Restrictions.like("name","abc"));
criteria.add(Restrictions.hasMembers("address.name", "北京"));
criteria.add(Restrictions.hasMembers("provinces", "110000", "120000"));List<UserInfo> users = userInfoService.findAll(criteria);
Page page = userRepository.findAll(criteria, new PageRequest(0, 10));
处理一对多的查询:
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
CriteriaBuilder builder) {
Path expression;
//此处是表关联数据,注意仅限一层关联,如user.address,
//查询user的address集合中,address的name为某个值
if (fieldName.contains(".")) {
String[] names = StringUtils.split(fieldName, ".");
//获取该属性的类型,Set?List?Map?
expression = root.get(names[0]);
Class clazz = expression.getJavaType();
if (clazz.equals(Set.class)) {
SetJoin setJoin = root.joinSet(names[0]);
expression = setJoin.get(names[1]);
} else if (clazz.equals(List.class)) {
ListJoin listJoin = root.joinList(names[0]);
expression = listJoin.get(names[1]);
} else if (clazz.equals(Map.class)) {
MapJoin mapJoin = root.joinMap(names[0]);
expression = mapJoin.get(names[1]);
} else {
//是many to one时
expression = expression.get(names[1]);
}
} else {
//单表查询
expression = root.get(fieldName);
}
FetchType应用:
fetch = FetchType.EAGER 作用
如果是EAGER,那么表示取出这条数据时,它关联的数据也同时取出放入内存中
如果是LAZY,那么取出这条数据时,它关联的数据并不取出来,在同一个session中,什么时候要用,就什么时候取(再次访问数据库)。
但是,在session外,就不能再取了。用EAGER时,因为在内存里,所以在session外也可以取。
一般只在一边设Eager,JPA接口默认为一对多为Lazy,多对一为Eager,但是Hibernate反向工程生成Entity时,多对一为Lazy,
需要手动改为Eager
。
Spring配置JPA和使用:
http://blog.sina.com.cn/s/blog_4fb490ff0100xbly.html