springBoot整合springDataJpa

毫无疑问,第一步引入依赖

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

第二步,编写application.yml的配置文件:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      connection-timeout: 30000
      minimum-idle: 10
      maximum-pool-size: 65
      idle-timeout: 60000
      max-lifetime: 600000
      auto-commit: true
      pool-name: MyHikariCP
      leak-detection-threshold: 5000
      connection-test-query: SELECT 1
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
    database: mysql

ORM框架的思想就是通过java对象去操作数据库,那么下面我们创建实体类,通过实体类去生成数据库表。

@EqualsAndHashCode(callSuper = true)
@Data
@Entity
@Table(name = "t_user")
@Accessors(chain = true)
public class User extends BaseEntity implements Serializable {
    private String userName;
    private String password;
    private String age;
    private String gender;
    private String email;
}

对于实体类上共同有的一些字段的封装

@EqualsAndHashCode(callSuper = true)
@Data
@MappedSuperclass  //不单独映射成一张表,但是将它和继承它的子类一起映射成一张表
@EntityListeners(AuditingEntityListener.class) //在jpa.save方法被调用的时候,时间字段会自动设置并插入数据库,但是CreatedBy和LastModifiedBy并没有赋值,因为需要实现AuditorAware接口来返回你需要插入的值。
public class BaseEntity extends LogicalDeleteEntity implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @JsonIgnore
    @CreatedBy
    @Column(name = "created_by",nullable = false,updatable = false)
    private String createdBy;

    @JsonIgnore
    @CreatedDate
    @Column(name = "created_date",updatable = false)
    private LocalDateTime createdDate;

    @JsonIgnore
    @LastModifiedBy
    @Column(name = "last_modified_by")
    private String lastModifiedBy;

    @JsonIgnore
    @LastModifiedDate
    @Column(name = "last_modified_date")
    private LocalDateTime lastModifiedDate;

}

逻辑删除

@MappedSuperclass
public class LogicalDeleteEntity implements LogicalDeleteTable, Serializable {
    private static final Long serialVersionUID = 1L;

    @JsonIgnore
    @Column(name = "is_deleted", nullable = false)
    protected boolean deleted;

    @Override
    public boolean isDeleted() {
        return this.deleted;
    }

    @Override
    public void setDeleted(boolean deleted) {
        this.deleted = deleted;
    }
}
public interface LogicalDeleteTable {

boolean isDeleted();

void setDeleted(boolean deleted);
}

配置自动插入时间;此处应有登录功能,获取登录信息,设置创建人和修改人的

@Configuration
public class AuditorConfig implements AuditorAware<String> {
    @Override
    public Optional<String> getCurrentAuditor() {
        return Optional.of("张三");
    }
}

配置启动类

@SpringBootApplication
@EnableJpaAuditing  //自动插入时间
@EnableTransactionManagement  //事务
@EnableJpaRepositories(basePackages = "com.ddh.springdatajpa.mapper")  //相当于@MapperScan
public class SpringdatajpaApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringdatajpaApplication.class, args);
    }

}

下面配置dao层,(个人习惯使用mybatis,所以命名风格上有所偏好,勿介勿介)

@Repository
public interface UserMapper extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
    
}

简单的API调用不说了,现在只想分享一下,JpaSpecificationExecutor的动态条件查询
一个封装的请求参数:

@Data
public class QueryParam<T> implements Serializable {
    private T param;
    private String searchValue;
}

service层进行业务的处理

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    public List<User> searchByLike(QueryParam<User> param) {
        User user = param.getParam();
        String searchValue = param.getSearchValue();
        List<User> userList = userMapper.findAll(new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                ArrayList<Predicate> list = new ArrayList<>();
                if (StringUtils.isNotBlank(user.getGender())) {
                    Predicate p1 = builder.equal(root.get("gender").as(String.class), user.getGender());
                    list.add(p1);
                }
                if (StringUtils.isNotBlank(searchValue)) {
                    Predicate p3 = builder.like(root.get("userName").as(String.class), "%"+searchValue+"%");
                    Predicate p4 = builder.like(root.get("email").as(String.class),"%"+searchValue+"%");
                    list.add(builder.or(p3,p4));
                }

                query.where(list.toArray(new Predicate[list.size()]));

                return query.getRestriction();
            }
        });
        return userList;
    }
}

测试一下:

@SpringBootTest
@Slf4j
class SpringdatajpaApplicationTests {
    @Autowired
    UserService userService;
    @Test
    void contextLoads() {
        User user = new User().setGender("女性").setUserName("杨");
        log.info(user.toString());
        QueryParam<User> param = new QueryParam<User>();
        param.setParam(user);
        param.setSearchValue("8");
        List<User> users = userService.searchByLike(param);
        log.info(users.toString());
    }
}

控制台打印的sql:

select user0_.id as id1_0_, user0_.is_deleted as is_delet2_0_, user0_.created_by as created_3_0_, user0_.created_date as created_4_0_, user0_.last_modified_by as last_mod5_0_, user0_.last_modified_date as last_mod6_0_, user0_.age as age7_0_, user0_.email as email8_0_, user0_.gender as gender9_0_, user0_.password as passwor10_0_, user0_.user_name as user_na11_0_ from t_user user0_ where user0_.gender=? and (user0_.user_name like ? or user0_.email like ?)

控制台打印的结果:

[User(userName=秋香, password=948422, age=28, gender=女性, email=448494564@163.com), User(userName=杨幂, password=3481155, age=30, gender=女性, email=8425445@163.com)]

因为上面的业务踩过的坑:
1.做模糊查询的时候,要自己加 "%".
2.spring data jpa对逻辑删除不是很友好,直接调用delete()方法是物理删除。添加

@SQLDelete(sql = "update t_user set is_deleted=1 and id =? ")
@SQLDeleteAll(sql = "update t_user set is_deleted=1 and id =?")
@Where(clause = "id_deleted=0")

只能是对单个Entity有效,限制太大。
3.因为是多条件查询,如果你每一个条件都设一下query.where();那么前面的条件会被后面的覆盖掉
eg:

                if (StringUtils.isNotBlank(user.getGender())) {
                    query.where(builder.equal(root.get("gender").as(String.class), user.getGender()));
                }
                if (StringUtils.isNotBlank(user.getUserName())){
                    query.where(builder.like(root.get("userName").as(String.class), "%"+searchValue+"%"));
                }
                //前面的条件没有了,被覆盖了
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容