前言

1、本文将详细阐述如何使用JPA框架对数据库实现增删改查操作,业务中比较常见的应用场景几乎在这里都能看到,并且有详尽的代码可供直观演示,其中遇到的坑也进行了实时标注。
2、JPA的环境配置在前面的章节已有总结,不再赘述,直接上干货。

环境准备
步骤1:创建实体类对象

@Entity	//该注解必须加,表明这是一个与数据库映射的实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "merchant_info") //项目启动后数据库会自动创建merchant_info表
@ApiModel(value = "商户信息表") //该注解以及后续controller中所有以@Api开头的注解表明引入swagger框架,可不加,丝毫不影响,我是为了便于用wagger调用接口演示。
public class MerchantInfo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) //必须加该注解,表明id自增,且唯一
    @ApiModelProperty(value = "主键id")
    private Long id;

    @ApiModelProperty(value = "商户名称")
    private String merchantName;

    @ApiModelProperty(value = "城市名称")
    private String cityName;

    @ApiModelProperty(value = "父对象id")
    private Long parentId;

    @ApiModelProperty(value = "商户状态: 1 生效 2 失效")
    private Long status;

    @ApiModelProperty(value = "随机生成码")
    private String invitationCode;

    @ApiModelProperty(value = "创建时间")
    private Date createTime;

    @ApiModelProperty(value = "更新时间")
    private Date updateTime;

    @ApiModelProperty(value = "备注")
    private String remark;

    @ApiModelProperty(value = "负责人")
    private String principal;

    @ApiModelProperty(value = "负责人联系方式")
    private String principalPhone;

}

步骤2:创建与实体类MerchantInfo相关的JPA接口,并使其继承JpaRepository接口,泛型传递<MerchantInfo, Long>

//此注解必加,表明它是一个bean类,项目启动后spring容器扫描到该注解,会将该类初始化成bean对象,便于其他程序调用
@Component
public interface MerchantInfoJpaRepository extends JpaRepository<MerchantInfo,Long> {
}

步骤3:SpringBoot主程序入口,如果只用JPA框架,相关的配置只需加@EnableJpaRepositories注解即可

@SpringBootApplication
@EnableJpaRepositories
public class WebapitestApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebapitestApplication.class, args);
    }
}

步骤4:创建Controller类
下面是controller类整体格式,后面对数据库表merchant_info进行增删改查的所有代码都会在这个controller类里书写。

@RestController //此注解等同于@Controller(用在类上) + @ResponseBody(用在方法上)注解组合
@Slf4j	//该注解可以在程序中直接使用log.info()打印日志
@Api(tags = "数据库表merchant_info进行增删改查") //此项是swagger的注解,可以不加,丝毫不影响
public class MerchantInfoController {

    @Autowired
    private MerchantInfoJpaRepository merchantInfoJpaRepository;
    
    方法1: ...{}
    方法2: ...{}
    方法3: ...{}
    }
 }

JPA查询功能

1、findAll()方法:无条件查询merchant_info表中所有数据

步骤1:Controller中代码如下:

public class MerchantInfoController {
    @Autowired
    private MerchantInfoJpaRepository merchantInfoJpaRepository;
    /**
     *  JPA findAll() 无条件查询表中所有数据
      * @return
     */
    @GetMapping("/getAllMerchantInfo")
    @ApiOperation(value = "获取所有商户信息")
    public List<MerchantInfo> getAllMerchantInfo(){
        List<MerchantInfo> merchantInfoList = merchantInfoJpaRepository.findAll();
        log.info("打印所有商户列表:{}",merchantInfoList);
        return merchantInfoList;
    }
    }
 }

步骤2:接口调用:http://localhost:8080/getAllMerchantInfo
步骤3:接口返回结果:

[
  {
    "id": 1,
    "merchantName": "广州泽天君成科技有限公司",
    "cityName": "广州",
    "parentId": null,
    "status": 2,
    "invitationCode": "207717",
    "createTime": "2021-03-23T03:37:00.000+00:00",
    "updateTime": "2021-04-27T09:02:11.000+00:00",
    "remark": null,
    "principal": null,
    "principalPhone": null
  },
  {
    "id": 2,
    "merchantName": "广州市青豪企业管理有限责任公司",
    "cityName": "温州",
    "parentId": null,
    "status": 2,
    "invitationCode": "126155",
    "createTime": "2021-03-23T03:43:43.000+00:00",
    "updateTime": "2021-04-27T06:47:00.000+00:00",
    "remark": null,
    "principal": null,
    "principalPhone": null
  },
  ...
  省略若干
  ...
]

2、findById(Long id)方法:根据id查询merchant_info表中对应的数据

步骤1:Controller中代码如下:

/**
     * JPA findById(Long id) 根据主键id查询表中相应数据
     * @param id
     * @return
     */
    @GetMapping("/getMerchantById")
    @ApiOperation(value = "获取指定id的商户信息")
    @ApiImplicitParam(name = "id",value = "商户id",required = true,defaultValue = "15")
    public MerchantInfo getMerchantById(@RequestParam(name = "id") Long id){
        Optional<MerchantInfo> merchantInfoOptional = merchantInfoJpaRepository.findById(id);
        MerchantInfo merchantInfo = merchantInfoOptional.get();
        log.info("打印id={}的商户信息为:{}",id,merchantInfo);
        return merchantInfo;
    }

步骤2:调用接口:http://localhost:8080/getMerchantById?id=15
步骤3:接口返回结果如下:

{
  "id": 15,
  "merchantName": "浙江橙米企业管理有限公司",
  "cityName": "绍兴",
  "parentId": null,
  "status": 2,
  "invitationCode": "342149",
  "createTime": "2021-03-23T03:43:43.000+00:00",
  "updateTime": "2021-04-26T09:11:50.000+00:00",
  "remark": null,
  "principal": null,
  "principalPhone": null
}

3、findAllById(Iterable<ID> var1)方法:根据传入的多个id集合查询merchant_info表中对应的数据

步骤1:Controller中代码

/**
     * JPA  findAllById(Iterable<ID> var1) 查询多个id表中相应数据
     * @param ids
     * @return
     */
    @GetMapping("/getMerchantByIds")
    @ApiOperation(value = "获取多个id对应的商户信息")
    public List<MerchantInfo> getMerchantByIds(@RequestParam(name = "ids")  String ids ){
        log.info("打印后端接收post请求体数据 String[] ids:{}",ids);
        //将传入的数组字符串解析成JsonArray对象
        JSONArray jsonArray = JSON.parseArray(ids);
        log.info("打印转换后的JsonArray对象:{}",jsonArray); 
        List<Long> longList = new ArrayList<Long>();
        //遍历jsonArray对象取出id元素并添加到List集合中
        for (int i  = 0; i < jsonArray.size(); i++){
            longList.add(jsonArray.getLong(i));
        }
        log.info("打印转换后的Long集合:{}",longList);
        //查询longList集合中所有id对应的数据
        List<MerchantInfo> merchantInfoList = merchantInfoJpaRepository.findAllById(longList);
        log.info("打印商户集合:{}",merchantInfoList);
        return merchantInfoList;
    }

步骤2:接口调用:http://localhost:8080/getMerchantByIds?ids=%5B2%2C3%2C6%5D
Note:%5B %2C %5D分别代表[ , ],它们都是URL编码,实际上ids参数传递的是[2, 3, 6]只是不能明文传输,必须转成符合URL编码规则的格式。

步骤3:接口返回结果如下:

[
  {
    "id": 2,
    "merchantName": "广州市青豪企业管理有限责任公司",
    "cityName": "温州",
    "parentId": null,
    "status": 2,
    "invitationCode": "126155",
    "createTime": "2021-03-23T03:43:43.000+00:00",
    "updateTime": "2021-04-27T06:47:00.000+00:00",
    "remark": null,
    "principal": null,
    "principalPhone": null
  },
  {
    "id": 3,
    "merchantName": "苏州合和众科技有限公司",
    "cityName": "苏州",
    "parentId": null,
    "status": 2,
    "invitationCode": "807624",
    "createTime": "2021-03-24T09:23:05.000+00:00",
    "updateTime": "2021-04-27T06:46:58.000+00:00",
    "remark": null,
    "principal": null,
    "principalPhone": null
  },
  {
    "id": 6,
    "merchantName": "义乌市铃芝电动车行",
    "cityName": "杭州",
    "parentId": null,
    "status": 2,
    "invitationCode": "798048",
    "createTime": "2021-03-23T03:43:43.000+00:00",
    "updateTime": "2021-04-27T06:46:57.000+00:00",
    "remark": null,
    "principal": null,
    "principalPhone": null
  }
]

4、findAll(Example<S> example)方法:构建example查询条件进行查询

步骤1:Controller中代码

/**
     * JPA  List<S> findAll(Example<S> example) 构建example查询条件进行查询
     * @param merchantInfo
     * @return
     */
    @PostMapping("/getMerchantByExample")
    @ApiOperation(value = "根据example查询符合条件的商户信息")
    public List<MerchantInfo> getMerchantByExample(@RequestBody MerchantInfo merchantInfo){
        log.info("打印传入的请求体merchantInfo:{}",merchantInfo);
        //构建查询example
        Example<MerchantInfo> merchantInfoExample = Example.of(merchantInfo);
        //返回数据库中所有符合example查询条件对应的数据
        List<MerchantInfo> merchantInfoList = merchantInfoJpaRepository.findAll(merchantInfoExample);
        log.info("打印符合条件的商户列表:{}",merchantInfoList);
        return merchantInfoList;
    }

步骤2:接口调用
post
http://localhost:8080/getMerchantByExample
parameters:

{
	  "cityName": "广州",
	  "remark": null,
	  "status": 2
}

步骤3:接口返回结果

[
  {
    "id": 1,
    "merchantName": "广州泽天君成科技有限公司",
    "cityName": "广州",
    "parentId": null,
    "status": 2,
    "invitationCode": "207717",
    "createTime": "2021-03-23T03:37:00.000+00:00",
    "updateTime": "2021-04-27T09:02:11.000+00:00",
    "remark": null,
    "principal": null,
    "principalPhone": null
  },
  {
    "id": 4,
    "merchantName": "成都欧韵聚网络科技有限公司",
    "cityName": "广州",
    "parentId": null,
    "status": 2,
    "invitationCode": "859655",
    "createTime": "2021-03-23T03:37:00.000+00:00",
    "updateTime": "2021-05-10T03:22:48.000+00:00",
    "remark": null,
    "principal": null,
    "principalPhone": null
  }
]

5、findAll(Example<S> example, Pageable pageable)方法:构建example查询条件并进行分页查询

步骤1:Controller中代码

/**
     * JPA  <S extends T> Page<S> findAll(Example<S> example, Pageable pageable) 构建example查询条件,并进行分页查询
     * note: page起始页 0
     * @param page
     * @param size
     * @param merchantInfo
     * @return
     */
    @PostMapping("/findAllByPageAble/{page}/{size}")
    @ApiOperation(value = "查询结果翻页处理")
    public List<MerchantInfo> findAllByPageAble(@PathVariable("page") Integer page, @PathVariable("size") Integer size, @RequestBody MerchantInfo merchantInfo){
    	//根据前端传入的page和size,构建Pageable对象,用于后续的分页查询
        Pageable pageable = PageRequest.of(page-1,size);
        //根据前端传入的请求体构建Example查询条件
        Example<MerchantInfo> merchantInfoExample = Example.of(merchantInfo);
        Page<MerchantInfo> merchantInfoPage = merchantInfoJpaRepository.findAll(merchantInfoExample, pageable);
        //获取对应页的数据内容
        List<MerchantInfo> merchantInfoList = merchantInfoPage.getContent();
        log.info("打印第{}页,每页数量{}条,\n该页查询结果为:{}",page,size,merchantInfoList);
        return merchantInfoList;
    }

步骤2:接口调用
post:http://localhost:8080/findAllByPageAble/2/3
parameters

{
  "cityName": "广州",
  "remark": null,
  "status": 2
}

步骤3:接口返回结果

[
  {
    "id": 12,
    "merchantName": "中山市古镇超途餐饮服务部",
    "cityName": "广州",
    "parentId": null,
    "status": 2,
    "invitationCode": "689589",
    "createTime": "2021-03-23T03:43:43.000+00:00",
    "updateTime": "2021-05-10T03:22:34.000+00:00",
    "remark": null,
    "principal": null,
    "principalPhone": null
  },
  {
    "id": 13,
    "merchantName": "广州骑士之家数字科技有限公司",
    "cityName": "广州",
    "parentId": null,
    "status": 2,
    "invitationCode": "513000",
    "createTime": "2021-03-23T03:43:43.000+00:00",
    "updateTime": "2021-04-27T06:46:52.000+00:00",
    "remark": null,
    "principal": null,
    "principalPhone": null
  },
  {
    "id": 16,
    "merchantName": "六安市煜祥人力资源开发有限公司(深圳)",
    "cityName": "广州",
    "parentId": null,
    "status": 2,
    "invitationCode": "422057",
    "createTime": "2021-03-23T03:43:43.000+00:00",
    "updateTime": "2021-05-10T03:22:35.000+00:00",
    "remark": null,
    "principal": null,
    "principalPhone": null
  }
]

JPA新增、修改功能

1、save(S s)方法:可对传入的单个Entity对象映射到数据库表中实现新增数据或修改表数据功能

步骤1:Controller中代码

/**
     * JPA  <S extends T> S save(S s) save方法可是实现新增或修改功能
     * @apiNote 传入一个Entity对象,若该对象中存在主键id,则是修改;若主键不存在,则是新增
     * @param merchantInfo
     * @return
     */
    @PostMapping("/saveMerchantByEntity")
    @ApiOperation(value = "新增或修改商户信息")
    public MerchantInfo saveMerchantByEntity(@RequestBody MerchantInfo merchantInfo){
        //判断主键是否存在,若存在,则修改该主键对应的表记录
        if(merchantInfo.getId()!= null && merchantInfo.getId() > 0){
            MerchantInfo merchantInfo1 = merchantInfoJpaRepository.findById(merchantInfo.getId()).get();

            /**
             * copyProperties(source,target,ignoreProperties) 将源对象属性值反射到目标对象对应的属性上,如果不加ignoreProperties参数
             * 则源对象中属性值为null的值会覆盖掉目标对象中对应属性不为null的值,ignoreProperties参数可以指定源对象中不覆盖目标对象的属性。
             * 如果源对象不存在某个属性,而目标对象存在某个属性,这种情况反射后,目标对象的该属性不会被覆盖
             */
            BeanUtils.copyProperties(merchantInfo,merchantInfo1,new String[]{"createTime","invitationCode"});
            merchantInfo1.setUpdateTime(new Date());
            return merchantInfoJpaRepository.save(merchantInfo1);
        }else{
        	//若主键id不存在,则新增一条记录到数据库表中
            merchantInfo.setCreateTime(new Date());
            merchantInfo.setUpdateTime(new Date());
            MerchantInfo merchantInfo1 = merchantInfoJpaRepository.save(merchantInfo);
            return merchantInfo1;
        }
    }

步骤2:接口调用
post:http://localhost:8080/saveMerchantByEntity
parameters 1

//请求体中不存在id主键,因此是新增
{
  "cityName": "大理01",
  "invitationCode": "333333",
  "merchantName": "大理测试商户05",
  "principal": "马二麻子",
  "principalPhone": "18900001111"
}

parameters 2

//请求体中存在id主键54,因此是修改
{
  "id":54,
  "cityName": "大理01",
  "invitationCode": "333333",
  "merchantName": "大理测试商户099",
  "principal": "马二麻子",
  "principalPhone": "18900000000"
}

步骤3:接口返回结果
response 1:

{
  "id": 54,
  "merchantName": "大理测试商户05",
  "cityName": "大理01",
  "parentId": null,
  "status": null,
  "invitationCode": "333333",
  "createTime": "2021-05-12T08:56:25.763+00:00",
  "updateTime": "2021-05-12T08:56:25.763+00:00",
  "remark": null,
  "principal": "马二麻子",
  "principalPhone": "18900001111"
}

response 2:

{
  "id": 54,
  "merchantName": "大理测试商户099",
  "cityName": "大理01",
  "parentId": null,
  "status": null,
  "invitationCode": "333333",
  "createTime": "2021-05-12T08:56:26.000+00:00",
  "updateTime": "2021-05-12T09:01:40.810+00:00",
  "remark": null,
  "principal": "马二麻子",
  "principalPhone": "18900000000"
}

Note
a)接口传parameters 1,无id,则新增一条表记录,自增生成的主键ID值54,见response 1
b)接口传parameters 2,有id,则修改该id对应的表记录,见response 1

2、saveAll(Iterable<S> iterable)方法:可对传入的多个Entity对象集合映射到数据库表中实现批量新增数据或修改表数据功能

步骤1:Controller中代码

/**
     * JPA  <S extends T> List<S> saveAll(Iterable<S> iterable) saveAll方法可实现批量新增或修改功能
     * @param merchantInfoList
     * @return
     */
    @PostMapping("/saveMerchantByEntityList")
    @ApiOperation(value = "批量新增或修改商户信息")
    public List<MerchantInfo> saveMerchantByEntityList(@RequestBody List<MerchantInfo> merchantInfoList){
        //创建一个新List集合,装载处理后的Entity对象
        List<MerchantInfo> updateMerchantList = new ArrayList<MerchantInfo>();
        for (MerchantInfo merchantInfo : merchantInfoList){
            if (merchantInfo.getId() != null && merchantInfo.getId() > 0){
                //获取数据库中对应id的原始数据映射到entity
                MerchantInfo merchantInfo1 = merchantInfoJpaRepository.findById(merchantInfo.getId()).get();
                BeanUtils.copyProperties(merchantInfo,merchantInfo1,new String[]{"createTime","invitationCode"});
                merchantInfo1.setUpdateTime(new Date());
                updateMerchantList.add(merchantInfo1);
            }else{
                merchantInfo.setCreateTime(new Date());
                merchantInfo.setUpdateTime(new Date());
                updateMerchantList.add(merchantInfo);
            }
        }
        log.info("打印处理后的MerchantInfo对象集合:\n{}",updateMerchantList);
        //批量进行新增或修改
        List<MerchantInfo> merchantInfoList1 = merchantInfoJpaRepository.saveAll(updateMerchantList);
        return merchantInfoList1;
    }

步骤2:接口调用
post:http://localhost:8090/saveMerchantByEntityList
parameters

//参数数据中既有存在id的条目,又有不存在id的条目,有id的条目执行修改,无id的条目执行插入新增
[
  {
    "id":50,
    "merchantName": "大理测试商户01",
    "cityName": "大理01",
    "status": 1,
    "invitationCode": "888888",
    "principal":"臧三",
    "principalPhone":"13811112222"
  },
  {
    "id":51,
    "merchantName": "大理测试商户02",
    "cityName": "大理01",
    "status": 1,
    "invitationCode": "888888",
    "principal":"女四",
    "principalPhone":"1381111333333"
  },
  {
    "id":52,
    "merchantName": "大理测试商户03",
    "cityName": "大理01",
    "status": 1,
    "invitationCode": "999999",
    "principal":"万五",
    "principalPhone":"13811114444"
  },
{
    "merchantName": "大理测试商户04",
    "cityName": "大理01",
    "status": 1,
    "invitationCode": "713713",
    "principal":"万五赵六",
    "principalPhone":"13811115555"
  }
]

步骤3:接口返回结果

//前三条数据进行了修改,最后一条数据新增插入数据库中。
[
  {
    "id": 50,
    "merchantName": "大理测试商户01",
    "cityName": "大理01",
    "parentId": null,
    "status": 1,
    "invitationCode": "111222",
    "createTime": "2021-05-12T03:29:23.000+00:00",
    "updateTime": "2021-05-12T03:43:45.732+00:00",
    "remark": null,
    "principal": "臧三",
    "principalPhone": "13811112222"
  },
  {
    "id": 51,
    "merchantName": "大理测试商户02",
    "cityName": "大理01",
    "parentId": null,
    "status": 1,
    "invitationCode": "2222333",
    "createTime": "2021-05-12T03:29:23.000+00:00",
    "updateTime": "2021-05-12T03:43:45.845+00:00",
    "remark": null,
    "principal": "女四",
    "principalPhone": "1381111333333"
  },
  {
    "id": 52,
    "merchantName": "大理测试商户03",
    "cityName": "大理01",
    "parentId": null,
    "status": 1,
    "invitationCode": "333444",
    "createTime": "2021-05-12T03:29:23.000+00:00",
    "updateTime": "2021-05-12T03:43:45.923+00:00",
    "remark": null,
    "principal": "万五",
    "principalPhone": "13811114444"
  },
  {
    "id": 53,
    "merchantName": "大理测试商户04",
    "cityName": "大理01",
    "parentId": null,
    "status": 1,
    "invitationCode": "713713",
    "createTime": "2021-05-12T03:43:45.923+00:00",
    "updateTime": "2021-05-12T03:43:45.923+00:00",
    "remark": null,
    "principal": "万五赵六",
    "principalPhone": "13811115555"
  }
]

JPA删除功能
1、deleteAll()方法:删除merchant_info表中所有数据

	/**
     * JPA deleteAll() 删除表中所有数据
     * 删除对应数据库表中所有数据,谨慎操作
     */
    @GetMapping("/deleteAllMerchantInfo")
    @ApiOperation(value = "删除merchant_info表中所有数据")
    public void deleteAllMerchantInfo(){
        merchantInfoJpaRepository.deleteAll();
    }

2、deleteById(Long)方法:删除merchant_info表中对应id的数据

	/**
     * JPA deleteById(Long) 删除对应id的表数据
     * 删除数据库表中对应id的条目
     * @param id
     */
    @GetMapping("/deleteMerchantInfoById")
    @ApiOperation(value = "删除merchant_info表中对应id的数据")
    public void deleteMerchantInfoById(@RequestParam("id") Long id){
        merchantInfoJpaRepository.deleteById(id);
    }

3、delete(T t)方法:删除Entity对应的表数据

	/**
     * JPA delete(T t) 删除Entity对应的表数据
     * @param merchantInfo
     */
    @PostMapping("/deleteMerchantInfoByEntity")
    @ApiOperation(value = "删除Entity对象映射对应的表数据")
    public void deleteMerchantInfoByEntity(@RequestBody MerchantInfo merchantInfo){
        log.info("打印请求体merchantInfo对象:{}",merchantInfo);
        Example<MerchantInfo> merchantInfoExample = Example.of(merchantInfo);
        MerchantInfo merchantInfo1 = merchantInfoJpaRepository.findOne(merchantInfoExample).get();
        merchantInfoJpaRepository.delete(merchantInfo1);
    }

4、deleteAll(Iterable<? extends T> iterable)方法:删除merchant_info表中多条记录

	/**
     * JPA deleteAll(Iterable<? extends T> iterable)
     * @param merchantInfo
     */
    @PostMapping("/deleteMerchantInfoByEntitysList")
    @ApiOperation(value = "删除merchant_info表中多条记录")
    public void deleteMerchantInfoByEntitysList(@RequestBody MerchantInfo merchantInfo){
        Example<MerchantInfo> merchantInfoExample = Example.of(merchantInfo);
        List<MerchantInfo> merchantInfoList = merchantInfoJpaRepository.findAll(merchantInfoExample);
        merchantInfoJpaRepository.deleteAll(merchantInfoList);
    }

附merchant_info表结构

CREATE TABLE `merchant_info` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `merchant_name` varchar(150) DEFAULT NULL COMMENT '商户名称',
  `city_name` varchar(255) DEFAULT NULL COMMENT '城市名称',
  `parent_id` bigint DEFAULT NULL COMMENT '父商户Id',
  `status` int DEFAULT '1' COMMENT '状态:1:有效 2:无效',
  `invitation_code` varchar(64) DEFAULT NULL COMMENT '邀请码',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '修改时间',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注',
  `principal` varchar(64) DEFAULT NULL COMMENT '负责人',
  `principal_phone` varchar(64) DEFAULT NULL COMMENT '负责人电话',
  PRIMARY KEY (`id`)
)
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐