原因: 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] Win10 键盘输入的数字英文字体变宽, 胖英文, 如何处理

    输入法 点击右键,找到设置,点击进入. 开启 "全/半角切换" 快捷键为 "Shift + 空格",随后可以使用这个快捷键进行切换正常. Link:https: ...

  2. dotnet 读 WPF 源代码笔记 为什么自定义的 UserControl 用户控件不能跨程序集继承

    从设计上,用户控件 UserControl 就不是一个合适用来多次继承的类型,更不要说进行跨程序集继承自定义的 UserControl 用户控件.对于大部分的用户控件来说,都是采用组合现有的控件来实现 ...

  3. Django之路由层、视图层、模板层介绍

    一.Django请求生命周期 1.路由层urls.py Django 1.11版本 URLConf官方文档 1.1 urls.py配置基本格式 from django.conf.urls import ...

  4. 如何在局域网内两台电脑上进行webapi的在线调试

    原文地址:https://www.zhaimaojun.top/Note/5475298(我自己的博客) 局域网内WebApi的远程调试方法: 第一步:管理员方式运行Vs并打开需要运行的项目,如果已经 ...

  5. golang 中 strings 包的 Replace 用法介绍笔记

    函数申明: func Replace(s, old, new string, n int) string 官方描述为: 返回将s中前n个不重叠old子串都替换为new的新字符串,如果n<0会替换 ...

  6. CompletableFuture学习总结

    CompletableFuture 简介 在Java8中,CompletableFuture提供了非常强大的Future的扩展功能,可以帮助我们简化异步编程的复杂性,并且提供了函数式编程的能力,可以通 ...

  7. jeecgboot集成Mongodb

    1.引入jar包依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId ...

  8. Mono 支持LoongArch架构

    近期,著名的.NET开源社区Mono正式支持LoongArch(龙架构),目前LoongArch64架构已出现在.NET社区主干分支上. 详细内容可以跟踪 https://github.com/mon ...

  9. 23ai免费版本环境快速就绪

    笔者感受就是搞一套Oracle 23ai的学习测试环境,从未如此的简单高效. 因为近期Oracle 23ai这个话题很火,很多人也在找实验环境想亲自体验测试一番. 其实搞这样的环境没有任何的门槛,甚至 ...

  10. 【题解】A19337.火星背包

    \(\bf{用 CDQ 分治可以极大地提升程序运行的速度.}\) \(\bf{实测在本数据量下,可以在 \color{red}10ms\color{normal}} 内通过所有的测试点!\) 关于折半 ...