jpa初级用法
前言:公司新的项目使用的jpa,之前没有过,所以在此小结一下
一、Spring data JPA简介
Spring data JPA是Spring在ORM(对象关系映射)框架,以及JPA规范的基础上,封装的一套JPA应用框架,并提供了一整套的数据访问层解决方案。
二、JPA优缺点
使用jpa也有一段时间了,在我看来jpa的优点很明显:
1.对于单表查询十分快捷方便,不需要像mybatis一样写sql,只需要在dao层按jpa命名规范调方法就好了
2.我们当前项目使用的数据库是mysql,jpa的一大作用就是数据库无关性,也就是说,以后项目改用oracle或者其他数据库时,我们不需要做任何处理,数据库可以轻松实现迁移。
但是呢,jpa的缺点也很明显,就是写复杂查询真的很蛋疼,像什么查询条件来自不同表,需要关联好几张表,有需要分页,需要排序,业务一复杂就脑壳疼(ps:可能还是太菜了)
注意:JPA 对多表复杂查询很不友好,JPA核心就是为了尽量不用多表查询,所有在表设计这块应该再三斟酌。另外,JPA的
@OneToMany,@OneToOne表关联查询注解我开发时是不用的
三、初级查询
3.1 常见注解
二.JPA常用注解
注解 | 解释 |
---|---|
@Entity | 声明类为实体或表。 |
@Table | 声明表名。 |
@Basic | 指定非约束明确的各个字段。 |
@Embedded | 指定类或它的值是一个可嵌入的类的实例的实体的属性。 |
@Id | 指定的类的属性,用于识别(一个表中的主键)。 |
@GeneratedValue | 指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。 |
@Transient | 指定的属性,它是不持久的,即:该值永远不会存储在数据库中。 |
@Column | 指定持久属性栏属性。 |
@SequenceGenerator | 指定在@GeneratedValue注解中指定的属性的值。它创建了一个序列。 |
@TableGenerator | 指定在@GeneratedValue批注指定属性的值发生器。它创造了的值生成的表。 |
@AccessType | 这种类型的注释用于设置访问类型。如果设置@AccessType(FIELD),则可以直接访问变量并且不需要getter和setter,但必须为public。如果设置@AccessType(PROPERTY),通过getter和setter方法访问Entity的变量。 |
@JoinColumn | 指定一个实体组织或实体的集合。这是用在多对一和一对多关联。 |
@UniqueConstraint | 指定的字段和用于主要或辅助表的唯一约束。 |
@ColumnResult | 参考使用select子句的SQL查询中的列名。 |
@ManyToMany | 定义了连接表之间的多对多一对多的关系。 |
@ManyToOne | 定义了连接表之间的多对一的关系。 |
@OneToMany | 定义了连接表之间存在一个一对多的关系。 |
@OneToOne | 定义了连接表之间有一个一对一的关系。 |
@NamedQueries | 指定命名查询的列表。 |
@NamedQuery | 指定使用静态名称的查询。 |
3.2 jpa 简单查询
3.2.1使用 @Query 创建查询
查询
方式一:原生sql查询
@Query(value = "select user_id,user_name,.. from user_info where userId= :userId", nativeQuery = true)
Object[] findByUserId(@Param("userId") Long userId);
方式二:使用jpa的查询方式
查询部分字段
@Query(value = "select userId,userName,.. from userInfo where userId= :userId")
User findByUserId(@Param("userId") Long userId);
查询所有字段
@Query(value = "select info from UserInfo info where info.userId= :userId")
User findByUserId(@Param("userId") Long userId);
UserInfo 是和数据库映射的实体类,查询属性名是UserInfo 类中的字段名,而原生查询直接是数据库字段名
注意 :@Param 注解是一定要的
删除
方式一:原生sql删除
@Modifying
@Transactional(rollbackFor = Exception.class)
@Query(value = "delete from user_info where userId= :userId", nativeQuery = true)
void deleteByUserId(@Param("userId") Long userId);
方式二:使用jpa的删除方式
@Modifying
@Transactional(rollbackFor = Exception.class)
@Query("DELETE FROM StationUser where userId IN(:userIdList)")
int deleteByIds(@Param("userIdList") List<Long> userIdList);
修改和删除类似,注意修改、删除和查询是不同的,一定要加
@Modifying (必须要,否则会报错)
@Transactional(rollbackFor = Exception.class)
两个注解 ,@Transactional(rollbackFor = Exception.class)注解也可以不在方法名上加,在调用这个方法的service层的类上加也可以,如下
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class TestServiceImpl implements TestService {
...
}
3.2.2通过解析方法名创建查询
Keyword | Sample | JPQL snippet |
---|---|---|
And |
findByLastnameAndFirstname |
… where x.lastname = ?1 and x.firstname = ?2 |
Or |
findByLastnameOrFirstname |
… where x.lastname = ?1 or x.firstname = ?2 |
Is,Equals |
findByFirstname ,findByFirstnameIs , findByFirstnameEquals
|
… where x.firstname = ?1 |
Between |
findByStartDateBetween |
… where x.startDate between ?1 and ?2 |
LessThan |
findByAgeLessThan |
… where x.age < ?1 |
LessThanEqual |
findByAgeLessThanEqual |
… where x.age ⇐ ?1 |
GreaterThan |
findByAgeGreaterThan |
… where x.age > ?1 |
GreaterThanEqual |
findByAgeGreaterThanEqual |
… where x.age >= ?1 |
After |
findByStartDateAfter |
… where x.startDate > ?1 |
Before |
findByStartDateBefore |
… where x.startDate < ?1 |
IsNull |
findByAgeIsNull |
… where x.age is null |
IsNotNull,NotNull |
findByAge(Is)NotNull |
… where x.age not null |
Like |
findByFirstnameLike |
… where x.firstname like ?1 |
NotLike |
findByFirstnameNotLike |
… where x.firstname not like ?1 |
StartingWith |
findByFirstnameStartingWith |
… where x.firstname like ?1 (parameter bound with appended % ) |
EndingWith |
findByFirstnameEndingWith |
… where x.firstname like ?1 (parameter bound with prepended % ) |
Containing |
findByFirstnameContaining |
… where x.firstname like ?1 (parameter bound wrapped in% ) |
OrderBy |
findByAgeOrderByLastnameDesc |
… where x.age = ?1 order by x.lastname desc |
Not |
findByLastnameNot |
… where x.lastname <> ?1 |
In |
findByAgeIn(Collection<Age> ages) |
… where x.age in ?1 |
NotIn |
findByAgeNotIn(Collection<Age> age) |
… where x.age not in ?1 |
True |
findByActiveTrue() |
… where x.active = true |
False |
findByActiveFalse() |
… where x.active = false |
IgnoreCase |
findByFirstnameIgnoreCase |
… where UPPER(x.firstame) = UPPER(?1) |