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

总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论