• springdatajpa简介(转载)


    转载:

    https://blog.csdn.net/matafeiyanll/article/details/124603090

    https://blog.csdn.net/qq_42495847/article/details/107991361

    JPA全英文名叫Java Persistence API,就是java持久化API,是SUN公司推出的一套基于ORM的规范。

    Sun引入新的JPA ORM规范出于两个原因:

    其一,简化现有Java EE和Java SE应用开发工作;

    其二,Sun希望整合ORM技术,实现天下归一。

    Spring Data JPA 可以理解为 JPA 规范的再次封装抽象,底层还是使用了 Hibernate 的 JPA 技术实现。

    一、JPA基础

    整合SpringData JPA
    1.导入jar包依赖

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
    </dependency>

    2.添加配置文件

    在application.yml中添加datasource配置,或者

    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/blog?useUnicode=true&characterEncoding=utf-8
        username: root
        password: 123456
      jpa:
        hibernate:
          ddl-auto: update
        show-sql: true

    属性解析:

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

    创建一张entity对象

    @Data
    @Entity
    @Table(name = "task_info")
    public class TaskInfo implements Serializable {
        private static final long serialVersionUID = 8247978712837006424L;
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Integer id;
    
        private String projectCode;
        @ApiModelProperty("job名称")
        private String jobName;
    
        @NotEmpty
        @ApiModelProperty("task名称")
        private String name;
        //前端传
        private Long taskCode;
    
    
        String description;
    
        @NotEmpty
        @ApiModelProperty("任务类型")
        private String taskType;

    这里面使用了一些JPA的注解,但JPA注解远不止这些。

    基本注解

    基本注解包括@Entity、@Table、@Id、@IdClass、@GeneratedValue、@Basic、@Transient、@Column、@Temporal、 @Enumerated、@Lob。

    @Entity定义对象将会成为被JPA管理的实体,将映射到指定的数据库表。
    @Table指定数据库的表名。
    @Id定义属性为数据库的主键,一个实体里面必须有一个。
    @IdClass利用外部类的联合主键。
    @GeneratedValue为主键生成策略
    @Basic表示属性是到数据库表的字段的映射。如果实体的字段上没有任何注解,默认即为@Basic。
    @Transient表示该属性并非一个到数据库表的字段的映射,表示非持久化属性,与@Basic作用相反。JPA映射数据库的时候忽略它。
    @Column定义该属性对应数据库中的列名。
    @Temporal用来设置Date类型的属性映射到对应精度的字段。
    @Lob 将属性映射成数据库支持的大对象类型,支持以下两种数据库类型的字段。

    关联关系注解
    @JoinColumn定义外键关联的字段名称
    @OneToOne关联关系
    @OneToMany与@ManyToOne可以相对存在,也可只存在一方。
    @ManyToMany表示多对多,和@OneToOne、@ManyToOne一样也有单向、双向之分。单向双向和注解没有关系,只看实体类之间是否相互引用。

    如果是使用jdbcTemplate或者mybatis,下一步肯定是要写SQL了。使用JPA不需要这一步,直接创建repository接口即可。

    public interface TaskInfoRepository extends JpaRepository<TaskInfo, Long> {
    
    
         List<TaskInfo> findByProjectCodeAndJobName(String projectCode, String jobName);
    
         @Transactional
         void deleteByProjectCodeAndJobName(String projectCode, String jobName) ;
    
    }

     二、批量操作

    如果直接引入repository,你会发现它已经内置了很多方法,这些方法都用SQL写也都能实现,但不知道要写到猴年马月。
    但是你会发现,repository提供了findAll的内置方法,但是我们还有一些saveAll(),updateAll(),deleteAll()的需求,要怎么办?

    JPA也考虑到了这个问题,提供了EntityManager供我们使用

    import javax.persistence.EntityManager;
    import javax.persistence.PersistenceContext;
    import javax.transaction.Transactional;
    
    
    @Service
    public class TaskInfoService {
        @PersistenceContext
        private EntityManager entityManager;
    
    //jpa 批量更新
        @Transactional
        public void saveAll(List<TaskInfo> taskInfoList) {
            for (TaskInfo taskInfo : taskInfoList) {
                entityManager.persist(taskInfo);
            }
    
        }
    
        @Transactional
        public void deleteAll(List<TaskInfo> taskInfoList) {
            for (TaskInfo taskInfo : taskInfoList) {
                entityManager.remove(taskInfo);
            }
        }
    }

    三、自定义SQL

    这样不管是单个对象的curd,还是批量对象的增删改查,JPA都可以搞定!

    但实际情况可能远比理论复杂,如果实际场景中JPA提供的方法不够用怎么办?

    没关系,JPA也是支持自定义SQL的。

    案例1:

    @Repository
    public interface StockRepository extends JpaRepository<IndexCalculated, String> {
    
        @Query(nativeQuery = true, value = "SELECT `stock_code` AS `stockCode`,`stock_name` AS `stockName`,`stock_display_name` AS `stockDisplayName` FROM `stock_security`")
        List<Map<String, Object>> stockIndexInfoOfStock();
    
        @Query(nativeQuery = true, value = "SELECT `index_code` AS `stockCode`,`index_name` AS `stockName`,`index_display_name` AS `stockDisplayName` FROM `index_info` WHERE `index_code` IN (SELECT `index_code` FROM `index_calculated`)")
        List<Map<String, Object>> stockIndexInfoOfIndex();
    
        @Query(nativeQuery = true, value = "SELECT `stock_code` FROM `sector_stock` WHERE `sector_code` IN ?1")
        List<Object> stockOfSector(String[] sectorCodeArr);
    
        @Query(nativeQuery = true, value = "SELECT `name` AS `sectorName`,`stock_code` AS `stockCode` FROM `industry_sector`,`sector_stock` WHERE industry_sector.`code`=sector_stock.`sector_code`")
        List<Map<String, Object>> industryOfStock();
    
        @Query(nativeQuery = true, value = "SELECT `index_code` AS `code`,`index_name` AS `name`,`index_display_name` AS `displayName` FROM `index_info` WHERE `index_code` IN (SELECT `index_code` FROM `index_calculated`)")
        List<Map<String, Object>> allIndexInfoOfCalculated();
    
        @Transactional
        @Modifying
        @Query(nativeQuery = true, value = "INSERT INTO `index_calculated`(`index_code`,`update_time`) VALUES (?1,?2)")
        int updateIndexCalculated(String indexCode, String updateTime);
        

    案例2:

    //示例1
    @Query("select t from Device t where t.deviceSn=:deviceSn and t.deleteFlag=1")
    Device findExistDevice(@Param("deviceSn") String deviceSn);
    //示例2
    @Query("select t from Device t where t.deviceSn=:deviceSn and t.deviceType =:deviceType and t.deleteFlag=1")
    Device findExistDevice(@Param("deviceSn") String deviceSn,@Param("deviceType")Integer deviceType);
    //示例3
    @Query("select t from Device t where t.deviceSn=?1 and t.deviceType = ?2 and t.deleteFlag=1")
    Device findDevice(String deviceSn,Integer deviceType);
    
    @Modifying
    @Query("update Device t set t.userName =:userName where t.id =:userId")
    User updateUserName(@Param("userId") Long userId,@Param("userName") String userName);

     四、唯一键的更新

    大家可以发现,jpa只有save,没有update,那我如果想update怎么办?这个时候分为两种情况

    1.你有主键ID

    jpa就是按照注解更新的,直接save即可

    2.没有主键ID,有业务上的unique id

    那就通过uniqueID先把对象查询出来,这个时候已经有主键ID了,将主键ID复制到原来要更新的对象上,save即可。

    贴一下代码

     @Test
        void save() {
            ProcessInfo byProjectCodeAndJobName = processInfoRepository.findByProjectCodeAndJobName("6012008297568", "job-111");
            ProcessInfo processInfo = new ProcessInfo();
            if (byProjectCodeAndJobName != null) {
                processInfo.setId(byProjectCodeAndJobName.getId());
            }
            processInfo.setJobName("job-111");
            processInfo.setProjectCode("6012008297568");
            processInfo.setLocations("[{\"taskCode\":6076344071520,\"x\":213,\"y\":328},{\"taskCode\":6076344071521,\"x\":600,\"y\":281}]");
            processInfo.setOwnership("default");
            processInfo.setGlobalParams("");
            processInfo.setDescription("job-111-update");
            ProcessInfo save = processInfoRepository.save(processInfo);
            System.out.println(save);
            
        }
  • 相关阅读:
    F#周报2019年第40期
    F#周报2019年第39期
    F#周报2019年第38期
    python模块之time_random
    python小趣味_520绘制一个心形.
    python模块之json_pickle_shelve
    python基础17_列表推导式 vs 生成器表达式
    python基础16_闭包_装饰器
    Spark安装笔记
    python基础15下_迭代器_生成器
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/16443153.html
Copyright © 2020-2023  润新知