您的位置:首页 > 编程语言 > Java开发

SpringBoot JPA 学习总结

2020-06-03 05:50 393 查看

1. 什么是JPA ?

全称Java Persistence API ,通俗来讲就是一套API框架,通过操作相应API,完成实体对象持久化存储到数据库的操作。

2 JPA 能做什么?

ORM映射元数据:通过注解或xml 配置方式,建立对象和表关系。(JPA支持XML和注解两种元数据的形式,元数据描述对象和表之间的映射关系,框架据此将实体对象持久化到数据库表中)

JPA 的API:一套执行CRUD 的操作API。封装了不同的方法进行操作。(用来操作实体对象,执行CRUD操作,框架在后台替我们完成所有的事情,开发者从繁琐的JDBC和SQL代码中解脱出来。)

查询语言:查询sql 时,通过对象进行查询,而非原生SQL.(通过面向对象而非面向数据库的查询语言查询数据,避免程序的SQL语句紧密耦合。)

JPA 本身是一套规范,其他厂商基于JPA 规范做了相应实现,比如Hibernate, Spring Data JPA 等。类似于Log4J 规范,向Logback,Slf4j 等具体实现了日志操作。

3. 接口约定关键字

关键字

描述

方法命名

样例

And

sql and 条件

findByUsernameAndPwd

where username = ? and pwd = ?

Or

sql or 条件

findByUserNameOrEmail

where username =? or email=?

Is,Equals

sql = 条件

findById,findByIdEquals

where id = ?

Between

sql between 条件

findByIdBetween

where id between ? and ?

LessThan

sql < 条件

findByIdLessThan

where id < ?

LessThanEquals

sql <= 条件

findByIdLessThanEquals

where id<=?

GreaterThan

sql > 条件

findByIdGreaterThan

where id > ?

GreaterThanEquals

sql >= 条件

findByIdGreaterThanEquals

where id >=?

After

sql > 条件

findByIdAfter

where id >?

Before

sql < 条件

findByIdBefore

where id < ?

IsNull

sql is null

findByIdIsNull

where id is null

NotNull

sql not null

findByIdNotNull

where id is not null

Like

sql like

findByNameLike

where name like ?

NotLike

sql not like

findByNameNotLike

where name not like ?

In

sql in

findByIdIn(Collection c)

where id in (?)

NotIn

sql not in

findByIdNotIn(Collection c)

where id not in (?)

StartingWith

sql like ?%

findByNameStartingWith

where name like '?%'

EndingWith

sql like %?

findByNameEndingWith

where name like '%?'

Containing

sql like %?%

findByNameContaining

where name like '%?%'

4 JPA 集成依赖

[code]<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

5. application 配置

[code]spring.datasource.url=jdbc:mysql://IP:3306/test?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=create
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

hbm2ddl.auto 配置需要注意

[code]create:每次加载hibernate时都会删除上一次的生成的表,然后根据你的model类再重新来生成新表,哪怕两次没有任何改变也要这样执行,这就是导致数据库表数据丢失的一个重要原因。
create-drop:每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
update:最常用的属性,第一次加载hibernate时根据model类会自动建立起表的结构(前提是先建立好数据库),以后加载hibernate时根据model类自动更新表结构,即使表结构改变了但表中的行仍然存在不会删除以前的行。要注意的是当部署到服务器后,表结构是不会被马上建立起来的,是要等应用第一次运行起来后才会。
validate:每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。

6. JPA 的使用

(1)常用注解:

@Entity 实体标注,数据库表和对象映射

@Id 标注一个字段是ID

@GeneratedValue 标注ID生成策略, 默认使用AUTO ,会在数据库中生成一张表,hibernate_sequence 存储ID的下一个值。

[code]public enum GenerationType {
TABLE,
SEQUENCE,
IDENTITY,
AUTO;

private GenerationType() {
}
}

@Column 标注列属性,大部分属性同数据库表字段,长度,是否非空等。

(2) 基本常用接口

创建Repository 接口 继承 JpaRepository<T,ID> ,基本常用操作都可以通过此接口完成。

[code]public interface AddressRepository extends JpaRepository<Address, Long> {
}
[code]@Resource
private AddressRepository addressRepository;

public void test(){
Address address=new Address();
address.setUserId(1L);
address.setCity("北京");
address.setProvince("北京");
address.setStreet("天安门");
addressRepository.save(address);
}

(3)方法覆盖,SQL 绑定

方法命名规则采用约定规则,SQL 使用对象的方式进行, 参数通过?数字的形式传递,参数内容为方法中的参数值

[code]public interface UserRepository extends JpaRepository<User, Long> {

User findByUserName(String userName);
User findByUserNameOrEmail(String username, String email);

@Transactional(timeout = 10)
@Modifying
@Query("update User set userName = ?1 where id = ?2")
int modifyById(String  userName, Long id);

@Transactional
@Modifying
@Query("delete from User where id = ?1")
void deleteById(Long id);

@Query("select u from User u where u.email = ?1")
User findByEmail(String email);

@Query("select u from User u")
Page<User> findALL(Pageable pageable);

Page<User> findByNickName(String nickName, Pageable pageable);

Slice<User> findByNickNameAndEmail(String nickName, String email,Pageable pageable);
}
[code]@Resource
private UserRepository userRepository;

public void test(){
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
String formattedDate = dateFormat.format(date);
User user=new User("ff", "ff123456","ff@126.com", "ff",  formattedDate);
List<User> u0 = userRepository.findAll();
Optional<User> u = userRepository.findById(3L);

String name = u.map(e -> e.getNickName()).get();

userRepository.save(user);
user.setId(2L);
userRepository.delete(user);
userRepository.count();
userRepository.estsById(3L);
}

(3) 复杂查询

[code]# 定义接口返回信息

public interface UserInfo {
String getUserName();
String getEmail();
String getHobby();
String getIntroduction();
}
[code]# 定义多表连接返回内容
public interface UserDetailRepository extends JpaSpecificationExecutor<UserDetail>,JpaRepository<UserDetail, Long>  {

UserDetail  findByHobby(String hobby);

@Query("select u.userName as userName, u.email as email, d.introduction as introduction , d.hobby as hobby from User u , UserDetail d " +
"where u.id=d.userId  and  d.hobby = ?1 ")
List<UserInfo> findUserInfo(String hobby);
}
[code]
@Resource
private UserDetailRepository userDetailRepository;

List<UserInfo> userInfos=userDetailRepository.findUserInfo("钓鱼");
for (UserInfo userInfo:userInfos){
System.out.println("userInfo: "+userInfo.getUserName()+"-"+userInfo.getEmail()+"-"+userInfo.getHobby()+"-"+userInfo.getIntroduction());
}

(4)条件组合查询

[code]# 定义接口

public interface UserDetailService {
public Page<UserDetail> findByCondition(UserDetailParam detailParam, Pageable pageable);
}

root 当前返回的对象类引用,可以获取对应参数,detailParam 获取参数对应值, cb 参数条件判断。predicates 组合where 条件。

[code]// 定义实现类

@Service
public class UserDetailServiceImpl implements  UserDetailService{

@Resource
private UserDetailRepository userDetailRepository;

@Override
public Page<UserDetail> findByCondition(UserDetailParam detailParam, Pageable pageable){

return userDetailRepository.findAll((root, query, cb) -> {
List<Predicate> predicates = new ArrayList<Predicate>();
//equal 示例
if (!StringUtils.isNullOrEmpty(detailParam.getIntroduction())){
predicates.add(cb.equal(root.get("introduction"),detailParam.getIntroduction()));
}
//like 示例
if (!StringUtils.isNullOrEmpty(detailParam.getRealName())){
predicates.add(cb.like(root.get("realName"),"%"+detailParam.getRealName()+"%"));
}
//between 示例
if (detailParam.getMinAge()!=null && detailParam.getMaxAge()!=null) {
Predicate agePredicate = cb.between(root.get("age"), detailParam.getMinAge(), detailParam.getMaxAge());
predicates.add(agePredicate);
}
//greaterThan 大于等于示例
if (detailParam.getMinAge()!=null){
predicates.add(cb.greaterThan(root.get("age"),detailParam.getMinAge()));
}
return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
}, pageable);

}
[code]//定义参数类
public class UserDetailParam {
private String userId;
private Integer minAge;
private Integer maxAge;
private String realName;
private String introduction;
private String city;

public String getUserId() {
return userId;
}

public void setUserId(String userId) {
this.userId = userId;
}

public Integer getMinAge() {
return minAge;
}

public void setMinAge(Integer minAge) {
this.minAge = minAge;
}

public Integer getMaxAge() {
return maxAge;
}

public void setMaxAge(Integer maxAge) {
this.maxAge = maxAge;
}

public String getRealName() {
return realName;
}

public void setRealName(String realName) {
this.realName = realName;
}

public String getIntroduction() {
return introduction;
}

public void setIntroduction(String introduction) {
this.introduction = introduction;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}
}
[code]@Resource
private UserDetailService userDetailService;
@Test
public void testFindByCondition()  {
int page=0,size=10;
Sort sort = new Sort(Sort.Direction.DESC, "id");
Pageable pageable = PageRequest.of(page, size, sort);
UserDetailParam param=new UserDetailParam();
param.setIntroduction("程序员");
param.setMinAge(10);
param.setMaxAge(30);
Page<UserDetail> page1=userDetailService.findByCondition(param,pageable);
for (UserDetail userDetail:page1){
System.out.println("userDetail: "+userDetail.toString());
}
}

总结,JPA 在Hibernate基础上更简化的封装常用的SQL CURD操作,大大简化的业务持久化操作,有优点也有缺点,复杂组合SQL 上,使用起来比较麻烦, 可以把基本操作和复杂操作分开,可以提高开发效率,具体还是跟团队使用吻合更好,有人喜欢纯SQL,有人系统Mybatis 框架,按需选择就是最好的选择。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: