SpringBoot整合SpringDataJPA

                                      SpringBoot整合SpringDataJPA

一、SpringData JPA是什么?

Spring Data JPA(Java Persistence API),是Spring框架的主要构建块之一。如果您想使用持久数据,它也是一个强大的工具。

Spring Data JPA的核心目标之一是减少代码并简化数据访问层,同时仍保留丰富且功能齐全的功能集。

SpringBoot整合SpringDataJPA_第1张图片

二、核心关键字

     JPQL(JavaPersistence Query Language)是一种面向对象的查询语言,它在框架中最终会翻译成为sql进行查询,如果不知JPQL请大家自行谷歌了解一下,如果你会SQL,了解这个应该不废吹灰之力。

使用SpringDataJPA进行JPQL/SQL一般查询的核心是@Query注解,我们先来看看该注解

@Retention(RetentionPolicy.RUNTIME)//运行时
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})//注解使用的注解位置为方法、注解类型
@QueryAnnotation
@Documented
public @interface Query {
    String value() default "";

    String countQuery() default "";

    String countProjection() default "";

    boolean nativeQuery() default false;

    String name() default "";

    String countName() default "";
}

@Retention元注解,RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在,即是运行时的状态。

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})//注解使用的注解位置为方法、注解类型

@QueryAnnotation标识这是一个查询注解;

@Documented 注解表明这个注解应该被 javadoc工具记录

@Query注解中有6个参数,value参数是我们需要填入的JPQL/SQL查询语句;nativeQuery参数是标识该查询是否为原生SQL查询,默认为false;countQuery参数为当你需要使用到分页查询时,可以自己定义(count查询)计数查询的语句,如果该项为空但是如果要用到分页,那么就使用默认的主sql条件来进行计数查询;name参数为命名查询需要使用到的参数,一般配配合@NamedQuery一起使用;countName参数作用与countQuery相似,但是使用的是命名查询的(count查询)计数查询语句;countProjection为涉及到投影部分字段查询时的计数查询(count查询)。

三、项目准备

3.1、采用springboot项目,

    
        1.8
    

    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.7.RELEASE
         
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
            org.springframework.boot
            spring-boot-starter-data-jpa
        

        
            mysql
            mysql-connector-java
            
            5.1.32
        

        
        
            com.alibaba
            fastjson
            1.2.55
        

        
        
            com.alibaba
            druid
            1.0.29
        

    
@SpringBootApplication
public class VdeMasterApplication {

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

}

3.2、application.properties配置

#######################################数据库配置##################################
spring.datasource.url=jdbc:mysql://192.168.3.7:3306/vde_dev?autoReconnect=true&useUnicode=true&characterEncoding=utf8&useSSL=false
#添加数据库连接池才需要
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=sa2019

#######################################SpringData配置##################################
#配置自动建表:updata:没有表新建,有表更新操作,控制台显示建表语句
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

3.3、数据库Sql准备:

CREATE TABLE `vde` (
  `id` int(11) NOT NULL COMMENT '自增ID',
  `board` varchar(255) DEFAULT NULL COMMENT '主板名称',
  `brand` varchar(255) DEFAULT NULL COMMENT '品牌名称',
  `device` varchar(255) DEFAULT NULL COMMENT '设备名',
  `display` varchar(255) DEFAULT NULL COMMENT '软件构建版本号',
  `manufacturer` varchar(255) DEFAULT NULL COMMENT '硬件制造商',
  `model` varchar(255) DEFAULT NULL COMMENT '型号',
  `os` varchar(255) DEFAULT NULL COMMENT '系统版本',
  `product` varchar(255) DEFAULT NULL COMMENT '手机厂商',
  `version` varchar(255) DEFAULT NULL COMMENT '固件版本号',
  `iccid` varchar(255) DEFAULT NULL COMMENT 'iccid',
  `imei` varchar(255) DEFAULT NULL COMMENT 'imei',
  `imsi` varchar(255) DEFAULT NULL COMMENT 'imsi',
  `ip` varchar(255) DEFAULT NULL COMMENT 'ip',
  `operator` varchar(255) DEFAULT NULL COMMENT '运营商',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='VDE信息表';
INSERT INTO `vde_dev`.`vde` (`id`, `board`, `brand`, `device`, `display`, `manufacturer`, `model`, `os`, `product`, `version`, `iccid`, `imei`, `imsi`, `ip`, `operator`) VALUES ('8', 'sdm710', '360', 'QK1809', 'V112', '360', '1809-A01', '8.1.0', 'QK1809', 'OPM1', '89860117801606100123', '869585031739071', '460015547625788', '10.98.223.11', '46001');
INSERT INTO `vde_dev`.`vde` (`id`, `board`, `brand`, `device`, `display`, `manufacturer`, `model`, `os`, `product`, `version`, `iccid`, `imei`, `imsi`, `ip`, `operator`) VALUES ('10', 'bullhead', 'google', 'bullhead', 'OPM7.181205.001', 'LGE', 'Nexus 5X', '8.1.0', 'bullhead', 'OPM7.181205.001', '89860117801058542442', '353627075256308', '460015547621765', '10.77.169.57', '46001');
INSERT INTO `vde_dev`.`vde` (`id`, `board`, `brand`, `device`, `display`, `manufacturer`, `model`, `os`, `product`, `version`, `iccid`, `imei`, `imsi`, `ip`, `operator`) VALUES ('11', 'QC_Reference_Phone', 'OnePlus', 'OnePlus3T', 'ONEPLUS A3010_28_171115', 'OnePlus', 'ONEPLUS A3010', '7.1.1', 'OnePlus3', 'NMF26F', '89860011191446092063', '864854036497043', '460028137299278', '10.28.79.195', '46000');
INSERT INTO `vde_dev`.`vde` (`id`, `board`, `brand`, `device`, `display`, `manufacturer`, `model`, `os`, `product`, `version`, `iccid`, `imei`, `imsi`, `ip`, `operator`) VALUES ('12', 'sdm636', 'xiaomi', 'whyred', 'PKQ1.180904.001', 'Xiaomi', 'Redmi Note 5', '9', 'whyred', 'PKQ1.180904.001', '89860317947552820897', '867192036035050', '460110415456028', '10.94.21.104', '46011');

3.4、解析

JpaRepository中,定义了一些常用的接口,里面的都可以直接使用。

@NoRepositoryBean
public interface JpaRepository extends PagingAndSortingRepository, QueryByExampleExecutor {
    List findAll();

    List findAll(Sort var1);

    List findAllById(Iterable var1);

     List saveAll(Iterable var1);

    void flush();

     S saveAndFlush(S var1);

    void deleteInBatch(Iterable var1);

    void deleteAllInBatch();

    T getOne(ID var1);

     List findAll(Example var1);

     List findAll(Example var1, Sort var2);
}

3.5、项目代码

@Entity
@Table(name = "vde")
public class Vde implements Serializable {

    @Id
    @GeneratedValue
    private Integer id;

    /**
     * 品牌名称
     */
    private String brand;

    /**
     * 型号
     */
    private String model;

    /**
     * 主板名称
     */
    private String board;

    /**
     * 系统版本
     */
    private String os;

    /**
     * 硬件制造商
     */
    private String manufacturer;

    /**
     * 版本
     */
    private String version;

    /**
     * 手机厂商
     */
    private String product;

    /**
     * 软件构建版本号
     */
    private String display;

    /**
     * 设备号
     */
    private String device;

    /**
     * imsi
     */
    private String imsi;

    /**
     * iccid
     */
    private String iccid;

    /**
     * imei
     */
    private String imei;

    /**
     * ip
     */
    private String ip;

    /**
     * 网络运营商
     */
    private String operator;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public String getBoard() {
        return board;
    }

    public void setBoard(String board) {
        this.board = board;
    }

    public String getOs() {
        return os;
    }

    public void setOs(String os) {
        this.os = os;
    }

    public String getManufacturer() {
        return manufacturer;
    }

    public void setManufacturer(String manufacturer) {
        this.manufacturer = manufacturer;
    }

    public String getVersion() {
        return version;
    }

    public void setVersion(String version) {
        this.version = version;
    }

    public String getProduct() {
        return product;
    }

    public void setProduct(String product) {
        this.product = product;
    }

    public String getDisplay() {
        return display;
    }

    public void setDisplay(String display) {
        this.display = display;
    }

    public String getDevice() {
        return device;
    }

    public void setDevice(String device) {
        this.device = device;
    }

    public String getImsi() {
        return imsi;
    }

    public void setImsi(String imsi) {
        this.imsi = imsi;
    }

    public String getIccid() {
        return iccid;
    }

    public void setIccid(String iccid) {
        this.iccid = iccid;
    }

    public String getImei() {
        return imei;
    }

    public void setImei(String imei) {
        this.imei = imei;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getOperator() {
        return operator;
    }

    public void setOperator(String operator) {
        this.operator = operator;
    }
}
@Query是用来配置自定义SQL的注解,后面参数nativeQuery = true才是表明了使用原生的sql,如果不配置,默认是false,则使用HQL查询方式。
HRL查询,查询全部信息,注意HRL查询的是实体类的名称,不是数据表的名称,特别注意这一点
@Repository
public interface VdeRepository extends JpaRepository {

    //@Query是用来配置自定义SQL的注解,后面参数nativeQuery = true才是表明了使用原生的sql,如果不配置,默认是false,则使用HQL查询方式。
    //HRL查询,查询全部信息,注意HRL查询的是实体类的名称,不是数据表的名称,特别注意这一点

    @Modifying
    @Query(value = "update vde v set v.imei=?1 where v.id=?2",nativeQuery = true)
    int updateImeiById(String imei,Integer id);

    //原生sql查询
    @Query(value = "select id  from vde where id = (SELECT MAX(id) from vde)", nativeQuery = true)
    public Integer queryMaxId();

    //hql查询
    @Query(value = "from Vde v where v.imei=?1 and v.model=?2")
    public Vde findByImeiAndModelFromHql(String imei, String model);

    //?查询
    @Query(value = "select * from vde v where v.imei=?1 and v.model=?2", nativeQuery = true)
    public Vde findByImeiAndModelFromSql(String imei, String model);

    //param查询
    @Query(value = "from Vde v where v.imei=:imei and v.imsi=:imsi")
    public Vde findByImeiAndImsiFromParam(@Param("imei") String imei, @Param("imsi") String imsi);

    //展示like模糊查询
    @Query(value = "from Vde v where v.imei like %:imeiLike%")
    List findByImeiLike(@Param("imeiLike")String imeiLike);

    //展示使用Spring自带分页查询
    @Query(value = "select * from vde v" ,nativeQuery = true)
    Page findAllPage(Pageable pageable);

    //展示带有条件的分页查询
    @Query(value = "from Vde v where v.imei like %:imeiLike%")
    Page findPageLikeImeiByHql(Pageable pageable, @Param("imeiLike")String imeiLike);

    //展示带有条件的分页查询
    @Query(value = "select *  from vde v where v.imei like %:imeiLike%",nativeQuery = true)
    Page findPageLikeImeiBySql(Pageable pageable, @Param("imeiLike")String imeiLike);

}

3.4、测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class VdeMasterApplicationTests {

    final Logger LOGGER = LoggerFactory.getLogger(VdeMasterApplicationTests.class);

    @Autowired
    private VdeRepository vdeRepository;

    @Test
    public void save() {
       Vde vde = new Vde();
       vde.setBoard("测试数据");
       vdeRepository.save(vde);
    }

    @Test
    public void delete() {
        vdeRepository.deleteById(14);
    }

    @Test
    @Transactional
    public void update() {
        //Executing an update/delete query 报错,需要加上事务处理
        vdeRepository.updateImeiById("imei_update",16);
    }

    @Test
    public void findAll() {
        LOGGER.info("findAll:" + vdeRepository.findAll().size());
    }

    @Test
    public void getMaxId() {
        LOGGER.info("maxId_native_sql:" + vdeRepository.queryMaxId());
    }

    @Test
    public void findByImeiAndModel() {
        LOGGER.info("vde_hql:" +vdeRepository.findByImeiAndModelFromHql("869585031739071","1809-A01"));
    }

    @Test
    public void findByImeiAndModelBySQL() {
        LOGGER.info("vde_native_sql:" +vdeRepository.findByImeiAndModelFromSql("869585031739071","1809-A01"));
    }

    @Test
    public void findByImeiAndModelByHQLAndParam() {
        LOGGER.info("vde_hql_param:" +vdeRepository.findByImeiAndImsiFromParam("869585031739071","460015547625788"));
    }

    @Test
    public void findByImeiLike() {
        LOGGER.info("vde_hql_like:" +vdeRepository.findByImeiLike("869585031739071"));
    }

    @Test
    public void findAllPage() throws Exception{
        //new PageRequest已经不推荐使用
        Pageable pageable = PageRequest.of(1,2);
        Page page  = vdeRepository.findAllPage(pageable);
        List list = page.getContent();
        LOGGER.info("findAllPage_sql:"+list);
    }

    @Test
    public void findPageLikeImei() throws Exception{
        //new PageRequest已经不推荐使用
        Pageable pageable = PageRequest.of(0,5,new Sort(Sort.Direction.ASC,"id"));
        Page page  = vdeRepository.findPageLikeImeiByHql(pageable,"869585031739071");
        List list = page.getContent();
        LOGGER.info("findPageLikeImei_hql:"+list);
    }

    @Test
    public void findPageLikeImeiBySql() throws Exception{
        //new PageRequest已经不推荐使用
        Pageable pageable = PageRequest.of(0,5,new Sort(Sort.Direction.ASC,"id"));
        Page page  = vdeRepository.findPageLikeImeiBySql(pageable,"869585031739071");
        List list = page.getContent();
        LOGGER.info("findPageLikeImeiBy_sql:"+list);
    }

}

3.5事务

事务一般是在service层,进行处理,例如:

public interface VdeService {

    /**
     * @param vde
     * @return
     * @throws Exception
     * @todo 添加VDE
     */
    public Vde add(Vde vde) throws Exception;

    /**
     * @return
     * @throws Exception
     * @todo 查询列表
     */
    public List list() throws Exception;

    /**
     * @return
     * @throws Exception
     * @todo 随机查询VDE
     */
    public Vde get() throws Exception;
}
@Service
public class VdeServiceImpl implements VdeService {

    @Autowired
    private VdeRepository vdeRepository;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Vde add(Vde vde) throws Exception {
        return vdeRepository.save(vde);
    }

    @Override
    public List list() throws Exception {
        return vdeRepository.findAll();
    }

    @Override
    public Vde get() throws Exception {
        List list = vdeRepository.findAll();
        return list.get(list.size() - 1);
    }
}

每个方法已经进行测试,测试结果只展示个别:

添加数据:

SpringBoot整合SpringDataJPA_第2张图片

分页查询:

 

你可能感兴趣的:(SpringBoot系列)