原因: jpa 没有类似于mybatis的那种 拼接sql的方式 想动态更新 需要使用

CriteriaUpdate的方式 去一直拼接,其实大多数场景只要传入一个非空实体类,去动态拼接sql 

1.定义实体类 继承一个统一的类型

@Data
@ToString
@Entity
@Table(name = "sys_user")
@DynamicInsert
@JsonIgnoreProperties(ignoreUnknown = true)
@EntityListeners(SysUserListener.class)
public class SysUser extends BaseEntity {
// ... @Schema(description = "用户ID")
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_id")
private Long userId; // ... @Schema(description = "用户账号")
@NotBlank(message = "用户账号不能为空")
@Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符")
@Column(name = "user_name")
private String userName; }

2. java 反射 拿到id 和值 作为 更新的 主键

package com.ricoh.srcb.system.service;

import com.ricoh.srcb.system.entity.domain.SysMenu;
import com.ricoh.srcb.system.framework.web.domain.BaseEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.apache.commons.lang3.ObjectUtils; import javax.persistence.Column;
import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.*;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; @Service
@Slf4j
public abstract class GenericService<T extends BaseEntity> { @PersistenceContext
private EntityManager entityManager; /**
* Updates the given entity by setting non-null fields.
*
* @param entity The entity to update.
* @return The number of rows affected by the update.
*/
public int baseUpdate(T entity) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaUpdate<T> criteriaUpdate = criteriaBuilder.createCriteriaUpdate(entityClass());
Root<T> root = criteriaUpdate.from(entityClass()); Field idField = getIdFieldAndValue(entity).getKey();
Object idValue = getIdFieldAndValue(entity).getValue(); if (ObjectUtils.isEmpty(idValue)) {
throw new RuntimeException("jpa update id not null");
}
criteriaUpdate.where(criteriaBuilder.equal(root.get(idField.getName()), idValue));
boolean hasFieldsToUpdate = false; Field[] fields = entity.getClass().getDeclaredFields(); for (Field field : fields) {
boolean annotationPresent = field.isAnnotationPresent(Column.class);
if (!idField.getName().equals(field.getName())&&annotationPresent) { // Exclude the id field
try {
field.setAccessible(true);
Object value = field.get(entity);
if (ObjectUtils.isNotEmpty(value)) {
criteriaUpdate.set(field.getName(), value);
hasFieldsToUpdate = true;
}
} catch (IllegalAccessException e) {
throw new RuntimeException("Error accessing field: " + field.getName(), e);
}
}
} if (!hasFieldsToUpdate) {
throw new IllegalArgumentException("No fields to update");
}
log.info("update table {} ,sql:{}", entity.getClass().getName(), criteriaUpdate);
return entityManager.createQuery(criteriaUpdate).executeUpdate();
} private Map.Entry<Field, Object> getIdFieldAndValue(T entity) {
for (Field field : entity.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(Id.class)) {
field.setAccessible(true);
try {
Object value = field.get(entity);
return new AbstractMap.SimpleEntry<>(field, value);
} catch (IllegalAccessException e) {
throw new RuntimeException("Error accessing @Id field.", e);
}
}
}
throw new IllegalStateException("No @Id field found in entity class.");
} /**
* Finds an entity by its ID.
*
* @param id The ID of the entity to find.
* @return The found entity or null if not found.
*/
/**
* Finds entities based on non-null fields of the provided entity.
*
* @param queryEntity The entity used as a template for query conditions.
* @return A list of entities that match the query conditions.
*/
public List<T> findByCriteria(T queryEntity) {
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(entityClass());
Root<T> root = criteriaQuery.from(entityClass()); List<Predicate> predicates = new ArrayList<>(); Field[] fields = entityClass().getDeclaredFields(); for (Field field : fields) {
try {
field.setAccessible(true);
Object value = field.get(queryEntity);
if (ObjectUtils.isNotEmpty(value)) {
predicates.add(criteriaBuilder.equal(root.get(field.getName()), value));
}
} catch (IllegalAccessException e) {
throw new RuntimeException("Error accessing field: " + field.getName(), e);
}
} criteriaQuery.where(predicates.toArray(new Predicate[0]));
return entityManager.createQuery(criteriaQuery).getResultList();
} private Class<T> entityClass() {
Type superClass = getClass().getGenericSuperclass();
if (superClass instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) superClass;
Type entityType = parameterizedType.getActualTypeArguments()[0];
if (entityType instanceof Class) {
return (Class<T>) entityType;
} else {
throw new IllegalArgumentException("Expected a class type for the generic parameter but got " + entityType);
}
} else {
throw new IllegalArgumentException("Expected a ParameterizedType but got " + superClass);
}
} public abstract List<SysMenu> selectMenuList(SysMenu menu, Long userId);
}

 3.service 进行 继承这个类 进行通用查询和更新

@Service
public class SysMenuServiceImpl extends GenericService<SysMenu> implements ISysMenuService {
@Override
@Transactional
public Boolean updateRole(SysRole role) {
// 修改角色信息
baseUpdate(role);
return insertRoleMenu(role) > 0 ? true : false;
}

}

 

spring boot jpa 进行通用多条件动态查询和更新 接口的更多相关文章

  1. Spring Boot JPA的查询语句

    文章目录 准备工作 Containing, Contains, IsContaining 和 Like StartsWith EndsWith 大小写不敏感 Not @Query Spring Boo ...

  2. Spring Boot Jpa 多条件查询+排序+分页

    事情有点多,于是快一个月没写东西了,今天补上上次说的. JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将 ...

  3. spring boot JPA中实体类常用注解

    spring boot jpa中的注解很多,参数也比较多.没必要全部记住,但是经常查看官方文档也比较麻烦,记录一下一些常用的注解.通过一些具体的例子来帮助记忆. @Entity @Table(name ...

  4. Spring boot JPA 用自定义主键策略 生成自定义主键ID

    最近学习Spring boot JPA 学习过程解决的一些问题写成随笔,大家一起成长.这次遇到自定义主键的问题 package javax.persistence; public enum Gener ...

  5. Spring Boot JPA 连接数据库

    本文将介绍怎样在Spring Boot project中加入JPA作为持久化方式. 改动 pom.xml 依赖 与上一篇介绍的 jdbc 不同的是 spring-boot-starter-jdbc 改 ...

  6. Spring boot Jpa添加对象字段使用数据库默认值

    Spring boot Jpa添加对象字段使用数据库默认值 jpa做持久层框架,项目中数据库字段有默认值和非空约束,这样在保存对象是必须保存一个完整的对象,但在开发中我们往往只是先保存部分特殊的字段其 ...

  7. spring boot jpa 使用update 报错解决办法

    在spring boot jpa 中自定义sql,执行update操作报错解决办法: 在@Query(...)上添加 @Modifying@Transactional注解

  8. Spring Boot(五):Spring Boot Jpa 的使用

    在上篇文章Spring Boot(二):Web 综合开发中简单介绍了一下 Spring Boot Jpa 的基础性使用,这篇文章将更加全面的介绍 Spring Boot Jpa 常见用法以及注意事项. ...

  9. Spring Boot + JPA(hibernate 5) 开发时,数据库表名大小写问题

      (转载)Spring Boot + JPA(hibernate 5) 开发时,数据库表名大小写问题   这几天在用spring boot开发项目, 在开发的过程中遇到一个问题hibernate在执 ...

  10. Spring Boot Jpa 的使用

    Spring Boot Jpa 介绍 首先了解 Jpa 是什么? Jpa (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范.它为 Java 开发人员提供了一种 ...

随机推荐

  1. [FAQ] Composer, Content-Length mismatch

    1. $ composer config repos.packagist composer https://php.cnpkg.org$ composer config cache-files-max ...

  2. python3解析FreeSWITCH会议室列表信息

    操作系统 :CentOS 7.6_x64 FreeSWITCH版本 :1.10.9 Python版本:3.9.12 进行FreeSWITCH会议室相关功能开发过程中,会遇到需要解析会议室列表信息并进行 ...

  3. spire.Doc -Index was out of the range

    一直以来用的好好的,突然有一天出现:Index was out of the range   ED04211_邵武市易逸行软件技术服务有限公司(万顺出行)_其他 升级后问题: 1.合并单元格出现问题 ...

  4. ansible(10)--ansible的systemd模块

    1. systemd模块 功能:管理服务启动与停止,与 service 模块用法一致: 主要参数如下: 参数 说明 name 指定需要控制的服务名称 state 指定服务状态,其值可以为stopped ...

  5. 包含Symbol类型的对象遍历取key使用Reflect.ownKeys

    Reflect.ownKeys(target)等同于 Object.getOwnPropertyNames 与Object.getOwnPropertySymbols 之和

  6. Mac远程控制工具有哪些

    适用于Mac的远程控制工具有很多,这里我们给大家列举五个常用软件. 1.Apple Remote Desktop 苹果自带远程桌面正如其名称所承诺的那样.作为 Apple 出品的应用程序,您可以想象它 ...

  7. Django 安全性与防御性编程:如何保护 Django Web 应用

    title: Django 安全性与防御性编程:如何保护 Django Web 应用 date: 2024/5/13 20:26:58 updated: 2024/5/13 20:26:58 cate ...

  8. NumPy 数组迭代与合并详解

    NumPy 数组迭代 NumPy 数组迭代是访问和处理数组元素的重要方法.它允许您逐个或成组地遍历数组元素. 基本迭代 我们可以使用 Python 的基本 for 循环来迭代 NumPy 数组. 一维 ...

  9. swagger文档枚举类型描述

    背景: 问题:使用swagger作为api文档,但文档中的枚举类型仅显示枚举name,对于使用文档的人员来讲不容易理解 解决思路:枚举类型加上自定义的描述 解决方案 maven配置 <depen ...

  10. EDP .Net开发框架--组织架构

    职类 职类是将职务进行分类管理,并定义了职类标记和职级.职类标记会带入到该职类下的职务作为职务的标记,并为职务提供职级范围选择. "高管类"职类定义了其职级范围为"PM1 ...