首页 > 其他分享 >spring boot jpa 进行通用多条件动态查询和更新 接口

spring boot jpa 进行通用多条件动态查询和更新 接口

时间:2024-06-18 17:44:14浏览次数:16  
标签:return jpa spring getName boot entity field new import

原因: 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;
}

}

 

标签:return,jpa,spring,getName,boot,entity,field,new,import
From: https://www.cnblogs.com/hejunhong/p/18254805

相关文章

  • 毕业设计:人事管理系统,基于java+springboot+mysql
     一、前言介绍          困扰管理层的许多问题当中,人事管理是一定不敢忽视的一块。但是管理好人事又面临很多麻烦需要解决,例如有几个方面:第一,公司往往员工人数都比较多,如何保证能够管理到每一员工;第二,如何在工作琐碎,记录繁多的情况下将人事变动的情况反应......
  • 免费分享一套SpringBoot+Vue房地产销售管理系统【论文+源码+SQL脚本+PPT+开题报告】,帅
    大家好,我是java1234_小锋老师,看到一个不错的SpringBoot+Vue房地产销售管理系统,分享下哈。项目视频演示【免费】SpringBoot+Vue房地产销售管理系统Java毕业设计_哔哩哔哩_bilibili【免费】SpringBoot+Vue房地产销售管理系统Java毕业设计项目来自互联网,免费分享,仅供学习交流......
  • 【Spring注解】事务注解@Transactional
    @Transactional作用:就是在当前这个方法执行开始之前来开启事务,方法执行完毕之后提交事务。如果在这个方法执行的过程当中出现了异常,就会进行事务的回滚操作@Transactional注解书写位置:方法当前方法交给spring进行事务管理类当前类中所有的方法都交由spring进行事务管......
  • spring-boot 热部署
    1.引入依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope></dependency>2.修改pom文件中插件 3.setting设置 4.crtl+shift+alt+......
  • Spring Boot应用程序集成etcd
    以下是一个SpringBoot应用程序,集成etcd实现键值存储和查询的示例。我们将使用etcd提供的Java客户端jetcd来与etcd进行交互。dockercompose安装etcd使用dockercompose安装并启动etcd:etcd-compose.yml文件内容:version:'3.5'services:etcd:container_na......
  • springboot 项目jacoco 覆盖率测试
    1.POM<dependency><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.2</version></dependency> <plugin>......
  • Java项目:springboot优咪商城(计算机毕业设计)
    作者主页:Java毕设网 简介:Java领域优质创作者、Java项目、学习资料、技术互助文末获取源码一、项目介绍优咪网上购物体验系统1.该平台主要有两大功能:(1)浏览平台官方和认证作者提供的篮球相关信息,信息类型包括:视频,新闻,评论类文章,比赛结果(2)篮球周边商城,商品分类球......
  • springboot 集成shiro框架
    目录一、Shiro简介二、架构体系与专业术语三、Shiro与SpringSecurity的对比四、Shiro优缺点五、springboot集成Shiro一、Shiro简介        ApacheShiro是一个功能强大且易于使用的Java安全(权限)框架。Shiro可以完成:认证、授权、加密、会话管理、与Web集成......
  • 基于Java+SpringBoot+Vue+elementUI的学生宿舍管理平台的设计与开发
    第一章绪论1.1选题背景和意义1.2国内外学生宿舍管理平台现状第二章相关技术简介2.1开发工具介绍2.1.1IDEA2.1.2VSCode2.1.3Navicat2.1.4宝塔面板2.2关键技术介绍2.2.1Java2.2.2SpringBoot2.2.3Mybatis2.2.4Vue2.2.5MySQL2.2.6Redis2.2.7E......
  • springboot引入第三方jar包本地lib并打包
    springboot引入第三方jar包本地lib并打包亲测可用一、在项目根目录创建lib目录并放入第三方lib包--project----lib(放在这儿)----src----target二、pom中引入第三方lib<!--自定义引入jar--><dependency><groupId>commons-io</groupId><artifac......