zoukankan      html  css  js  c++  java
  • SpringBoot整合系列-整合JPA

    原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9959865.html

    SpringBoot整合JPA进行数据库开发

    步骤

    第一步:添加必要的jar包

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>com.querydsl</groupId>
      <artifactId>querydsl-apt</artifactId>
      <version>${querydsl.version}</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>com.querydsl</groupId>
      <artifactId>querydsl-jpa</artifactId>
      <version>${querydsl.version}</version>
    </dependency>
    

    第二步:添加必要的配置

    spring.datasource.url = jdbc:h2:file:D:\testdb;DB_CLOSE_ON_EXIT=FALSE
    spring.datasource.username = sa
    spring.datasource.password = sa
    spring.datasource.driverClassName =org.h2.Driver
    

    第三步:添加实体,并添加注解

    @Entity  
    @Table(name = "USER")
    public class User {  
         @Id 
         @GeneratedValue(strategy = GenerationType.IDENTITY) 
         private int useId;
         @Column 
         private String useName; 
         @Column 
         private UseSex useSex; 
         @Column 
         private int useAge; 
         @Column(unique = true)
         private String useIdNo; 
         @Column(unique = true)
         private String usePhoneNum; 
         @Column(unique = true)
         private String useEmail; 
         @Column 
         private LocalDateTime createTime; 
         @Column 
         private LocalDateTime modifyTime;
         @Column 
         private UseState useState;
     }
    

    第四步:添加持久层

    @Repository  
    public interface UserRepository extends JpaRepository {  
    }
    

    注意:
    继承自JpaRepository的持久层可以直接使用其定义好的CRUD操作,其实只有增删查操作,关于修改的操作还是需要自定义的。

    第五步:持久层的使用

    @Service  
    public class UserService {  
         @Autowired 
         private UserRepository repository; 
         public ResponseEntity addUser(final User user) { 
             return new ResponseEntity<>(repository.save(user),HttpStatus.OK); 
         }
    }
    

    注意:其实在JpaRepository中已经定义了许多方法用于执行实体的增删查操作。

    JPA高级功能

    方法名匹配

    在UserRepository中定义按照规则命名的方法,JPA可以将其自动转换为SQL,而免去手动编写的烦恼,比如定义如下方法:

    User getUserByUseIdNo(String useIdNo);
    

    JPA会自动将其转换为如下的SQL:

    select * from USER where use_id_no = ?
    

    下面简单罗列方法命名规则:

    关键字 例子 sql
    And findByNameAndAge ...where x.name=?1 and x.age=?2
    Or findByNameOrAge ...where x.name=?1 or x.age=?2
    Between findByCreateTimeBetween ...where x.create_time between ?1 and ?2
    LessThan findByAgeLessThan ...where x.age < ?1
    GreaterThan findByAgeGreaterThan ...where x.age > ?1
    IsNull findByAgeIsNull ...where x.age is null
    IsNotNull,NotNull findByAgeIsNotNull ...where x.age not null
    Like findByNameLike ...where x.name like ?1
    NotLike findByNameNotLike ...where x.name not like ?1
    OrderBy findByAgeOrderByNameDesc ...where x.age =?1 order by x.name desc
    Not findByNameNot ...where x.name <>?1
    In findByAgeIn ...where x.age in ?1
    NotIn findByAgeNotIn ...where x.age not in ?1

    @Query注解

    使用@Query注解在接口方法之上自定义执行SQL。

    @Modifying
    @Query(value = "update USER set USE_PHONE_NUM = :num WHERE USE_ID= :useId", nativeQuery = true)
    void updateUsePhoneNum(@Param(value = "num") String num, @Param(value = "useId") int useId);
    

    上面的更新语句必须加上@Modifying注解,其实在JpaRepository中并未定义更新的方法,所有的更新操作均需要我们自己来定义,一般采用上面的方式来完成。

    /**
     * 表示一个查询方法是修改查询,这会改变执行的方式。只在@Query注解标注的方法或者派生的方法上添加这个注解,而不能
     * 用于默认实现的方法,因为这个注解会修改执行方式,而默认的方法已经绑定了底层的APi。
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
    @Documented
    public @interface Modifying {
    	boolean flushAutomatically() default false;
    	boolean clearAutomatically() default false;
    }
    

    JPQL(SQL拼接)

    使用JPQL需要在持久层接口的实现列中完成,即UserRepositoryImpl,这个类是UserRepository的实现类,我们在其中定义JPQL来完成复杂的SQL查询,包括动态查询,连表查询等高级功能。

    QBE(QueryByExampleExecutor)

    使用QBE来进行持久层开发,需要用到两个接口类,Example和ExampleMatcher,开发方式如下:

    List users = repository.findAll(Example.of(user));
    

    或者配合ExampleMarcher使用:

    ExampleMatcher matcher = ExampleMatcher.matching().withIgnoreCase();
    List users = repository.findAll(Example.of(user, matcher));
    

    以上逻辑一般位于service之中。其中user模型中保存着查询的条件值,null的字段不是条件,只有设置了值的字段才是条件。ExampleMatcher是用来自定义字段匹配模式的。

    处理枚举

    ​ 使用Spring-Data-Jpa时,针对枚举的处理有两种方式,对应于EnumType枚举的两个值:

    public enum EnumType {
        /** Persist enumerated type property or field as an integer. */
        ORDINAL,
        /** Persist enumerated type property or field as a string. */
        STRING
    }
    

    ​ 其中ORDINAL表示的是默认的情况,这种情况下将会将枚举值在当前枚举定义的序号保存到数据库,这个需要是从0开始计算的,正对应枚举值定义的顺序。STRING表示将枚举的名称保存到数据库中。

    ​ 前者用于保存序号,这对枚举的变更要求较多,我们不能随便删除枚举值,不能随意更改枚举值的位置,而且必须以0开头,而这一般又与我们定义的业务序号不一致,限制较多,一旦发生改变,极可能造成业务混乱;后者较为稳妥。

    ​ 正常情况下,如果不在枚举字段上添加@Enumerated注解的话,默认就以ORDINAL模式存储,若要以STRING模式存储,请在枚举字段上添加如下注解:

    @Enumerated(EnumType.STRING)
    @Column(nullable=false) // 一般要加上非null约束
    private UseState useState;
    

    分页功能

    ​ Spring-Data-Jpa中实现分页使用到了Pageable接口,这个接口将作为一个参数参与查询。

    ​ Pageable有一个抽象实现类AbstractPageRequest,是Pageable的抽象实现,而这个抽象类有两个实现子类:PageRequest和QPageRequest,前者现已弃用,现在我们使用QPageRequest来定义分页参数,其有三个构造器:

    public QPageRequest(int page, int size) {
        this(page, size, QSort.unsorted());
    }
    public QPageRequest(int page, int size, OrderSpecifier<?>... orderSpecifiers) {
        this(page, size, new QSort(orderSpecifiers));
    }
    public QPageRequest(int page, int size, QSort sort) {
        super(page, size);
        this.sort = sort;
    }
    

    ​ 在这里面我们可以看到一个QSort,这个QSort是专门用于与QPageRequest相配合使用的类,用于定义排序规则。默认情况下采用的是无排序的模式,即上面第一个构造器中的描述。

    ​ 要构造一个QSort需要借助querydsl来完成,其中需要OrderSpecifier来完成。

    ​ 这里有个简单的用老版本实现的分页查询:

        public ResponseEntity<Page<User>> getUserPage(final int pageId) {
            Sort sort = new Sort(new Sort.Order(Sort.Direction.DESC, "useId"));
            Page<User> users = repository.findAll(new PageRequest(pageId,2, sort));
            return new ResponseEntity<>(users, HttpStatus.OK);
        }
    

    ​ 至于新版本的分页查询和排序涉及内容较多较复杂,稍后再看。

    注意:分页首页页码为0

  • 相关阅读:
    git merge branch
    Notes on Large-scale Video Classification with Convolutional Neural Networks
    ubuntu shell编程笔记
    cpu-z for ubuntu 12.04 64bit : cpu-g
    Notation, First Definitions 转 http://brnt.eu/phd/node9.html
    textext for Inkscape
    read later
    Matlab远程调试 转
    Ubuntu中的在文件中查找和替换命令
    Ubuntu 下matlab 查看memory函数
  • 原文地址:https://www.cnblogs.com/V1haoge/p/9959865.html
Copyright © 2011-2022 走看看