jpa使用uuid策略后无法手动设置id的问题及解决

 更新时间:2024年08月12日 09:12:09   作者:流年ln  
这篇文章主要介绍了jpa使用uuid策略后无法手动设置id的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

jpa使用uuid策略后无法手动设置id

实体对象定义如下:

@Data
@Entity
@Table(name = "sys_user")
public class UserDO {

	/** 用户id */
	@Id
	@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
	@GeneratedValue(generator = "uuid")
	@Column(length = 36, nullable = false)
	private String userId;
	....
}

调用jpa的save方法,即使手动设置了id,手动设置的这个id也会被覆盖。

要求

当用户手动设置了id,以用户设置的id为准,否则使用uuid

解决方案

使用自定义id生成策略,判断id非空

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.id.UUIDGenerator;

import javax.persistence.Id;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 自定义uuid生成策略, 扩展 {@link org.hibernate.id.UUIDGenerator}
 * 当用户设置了id,以用户设置的id为主,为空则生成uuid
 * {@link javax.persistence.Id} 注解的字段只处理第一个
 *
 * @author qiudw
 * @date 7/7/2023
 */
@Slf4j
public class CustomerUuidGenerator extends UUIDGenerator {

	@Override
	public Serializable generate(SharedSessionContractImplementor session, Object obj) {
		Class<?> clazz = obj.getClass();
		log.debug("generate id class: {}", clazz.getName());
		Field[] fields = clazz.getDeclaredFields();
		try {
			for (Field field : fields) {
				Id idAnnotation = field.getAnnotation(Id.class);
				if (idAnnotation == null) {
					continue;
				}
				String fieldName = field.getName();
				log.debug("field name: {}", fieldName);
				String getMethodName = generateGetMethodName(fieldName);
				log.debug("get method name: {}", getMethodName);
				Method declaredMethod = clazz.getDeclaredMethod(getMethodName);
				String idValue = (String) declaredMethod.invoke(obj);
				if (StrUtil.isNotBlank(idValue)) {
					log.debug("use set value: {}", idValue);
					return idValue;
				}
			}
		} catch (NoSuchMethodException e) {
			log.error("no such method", e);
		} catch (InvocationTargetException | IllegalAccessException e) {
			log.error("invoke exception", e);
		}

		return super.generate(session, obj);
	}

	/**
	 * 生成get和set的方法名称
	 * type + 首字母大写(fieldName)
	 *
	 * @param fieldName userId
	 * @return type = set, fieldName = userId, 返回 setUserId
	 */
	private String generateGetMethodName(String fieldName) {
		return "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
	}

}

实体对象使用自定的策略

@Data
@Entity
@Table(name = "sys_user")
public class UserDO {

	/** 用户id */
	@Id
	@GenericGenerator(name = "uuid", strategy = "com.user.CustomerUuidGenerator")
	@GeneratedValue(generator = "uuid")
	@Column(length = 36, nullable = false)
	private String userId;
	....
}

现在可以手动设置id了

不设置则自动生成uuid

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Easycode自动化springboot的curd

    Easycode自动化springboot的curd

    这篇文章主要介绍了Easycode自动化springboot的curd,围绕主题的相关资料展开详细内容,具有一定的参考价值,需要的小伙伴可以参考一下,希望给对你有所帮助
    2022-01-01
  • 使用Java代码实现RocketMQ的生产与消费消息

    使用Java代码实现RocketMQ的生产与消费消息

    这篇文章介绍一下其他的小组件以及使用Java代码实现生产者对消息的生成,消费者消费消息等知识点,并通过代码示例介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-07-07
  • 解决java编译错误:程序包不存在的问题

    解决java编译错误:程序包不存在的问题

    出错:Error:(3, 27) java: 程序包com.aliyun.odps.udf不存在,遇到这样的错误问题如何解决呢,下面小编给大家带来了java编译错误:程序包不存在的问题及解决方法,感兴趣的朋友一起看看吧
    2023-05-05
  • Mybatis如何根据List批量查询List结果

    Mybatis如何根据List批量查询List结果

    这篇文章主要介绍了Mybatis如何根据List批量查询List结果,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • 简单说说Java SE、Java EE、Java ME三者之间的区别

    简单说说Java SE、Java EE、Java ME三者之间的区别

    本篇文章小编就为大家简单说说Java SE、Java EE、Java ME三者之间的区别。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-10-10
  • Java中Equals使用方法汇总

    Java中Equals使用方法汇总

    这篇文章主要采用问答的方式集中讲解了Java中Equals的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • java如何拷贝复制对象和集合问题

    java如何拷贝复制对象和集合问题

    这篇文章主要介绍了java如何拷贝复制对象和集合问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • java 与web服务器链接的实例

    java 与web服务器链接的实例

    这篇文章主要介绍了java 与web服务器链接的实例的相关资料,使用net.Socket类sock.getInetAddress()方法获得与Web服务器连接,需要的朋友可以参考下
    2017-07-07
  • java阿拉伯数字转中文数字

    java阿拉伯数字转中文数字

    这篇文章主要为大家详细介绍了java实现阿拉伯数字转换为中文数字,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-04-04
  • 关于文件上传MultipartBody的使用方法

    关于文件上传MultipartBody的使用方法

    这篇文章主要介绍了关于文件上传MultipartBody的使用方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06

最新评论