spring boot 最佳实践(十)-- spring data jpa

Quick start

1.pom引用

在spring boot中可以直接引入stater,该starter默认引入Hibernate依赖。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

如果使用mysql,还需要引入mysql驱动,使用mongoDB则引入mongoDB驱动。

2.配置

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/databasename
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver //驱动
  jpa:
    hibernate:
     show-sql: true  //日志中显示sql语句,生产环境需关闭

3.定义实体

实体是一个POJO类,属性必须有public的getter, setter方法。

@Entity
@Table(name = "person_info")
public class PersonInfo {

    @Id
    @GeneratedValue
    private Long id;

    @Column(name = "name", nullable = true, length = 20)
    private String name;

    @Column(name = "agee", nullable = true, length = 4)
    private int age;
}

如果没有定义@Table,@Column;jpa会默认将驼峰命名改为下划线命名映射到数据库。

实体定义常见注解

注解解释
@Entity声明类为实体或表。
@Table声明表名。
@Id指定的类的属性,用于识别(一个表中的主键)。
@GeneratedValue指定如何标识属性可以被初始化,例如自动、手动、或从序列表中获得的值。
@Transient指定的属性,它是不持久的,即:该值永远不会存储在数据库中。
@Column指定持久属性栏属性。
@Enumerated设置枚举类型

4.定义仓库

定义参考只需要继承JpaRepository接口即可。spring boot会自动创建接口的实现类。

public interface PersonInfoRepository extends JpaRepository<PersonInfo, Long> {
}

JpaRepository接口泛型两个参数分别表示实体对象类型和实体对象主键(ID)的类型。

实战建议

spring data jpa极大的简化了开发人员对实体持久化的工作,屏蔽了java程序员对数据库的操作。但在日常工作中经常存在各种错误的使用方案,具体说明如下。

1. 实体属性枚举值的定义

与表字段严格耦合的枚举应该定义在Entity类中,必须包含所有值域且没有多于的值。
例如PersonInfo的性别建议如下定义:

public class PersonInfo {
    @Enumerated(EnumType.STRING) 
    private Gender gender;
//... auttribue and getter setter
    
	public enum Gender{
	   unknow, male,female, //maybe some others , you konw -_-
	}
}

JPA默认映射的是@Enumerated(EnumType.ORDINAL) ,这时存储到DB中的是枚举的序号。所以即使我们不添加@Enumerated,JPA也可以正确的把枚举存储到数据库。

2.Repository的定义

Repository接口应该处理通用的实体持久化和查询逻辑,不能出现任何业务逻辑代码。
这样是有业务逻辑的反例:

    @Query("SELECT p FROM PersonInfo p WHERE p.gender= 'femal' AND p.age < :age ")
    PersonInfo  findMyGirl(@Param("age ") int age);

JPA场景下建议使用查询出完整Entity后,重置需要更新的属性,然后整体保存Entity。不建议写特定的sql更新某些具体的字段。
比如这样的代码就是更新反例:

    @Query("update PersonInfo set status=:status where id=:id")
    int updateStatusById(@Param("status") String status, @Param("id") int id);

2.Repository的使用

原则上不需要将Repository封装一层service给其他service调用。
比如这样纯属累赘:

    public class PersonInfoService{
        @Autowired PersonInfoRepository repository ;
    
         public void save(PersonInfo person){
               repository .save(person);
         }
    }

但是如果存在实体相关的通用查询逻辑被不同的service调用,就需要抽出通用的业务逻辑,避免代码重复。比如:

    public class PersonInfoService{
       @Autowired 
       PersonInfoRepository repository ;
    
        public List<PersonInfo>  findFemal(){
                repository.findAllByGender(PersonInfo.Gender.female);
         }
    }

参考文献
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/
SpringBoot系列(6)—SpringBoot-JPA
https://blog.csdn.net/tony308001970/article/details/74999680
spring boot 中使用 jpa以及jpa介绍
https://blog.csdn.net/wujiaqi0921/article/details/78789087
Hibernate中枚举Enum类型的映射策略
https://blog.csdn.net/lmy86263/article/details/52650721
Spring Data JPA 实战(一)-体系结构及基本配置
https://blog.csdn.net/sunhuiliang85/article/details/60482123
Spring JPA 使用@CreatedDate、@CreatedBy、@LastModifiedDate、@LastModifiedBy 自动生成时间和修改者
https://www.jianshu.com/p/14cb69646195

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值