jpa使用uuid策略后無法手動設(shè)置id的問題及解決
jpa使用uuid策略后無法手動設(shè)置id
實(shí)體對象定義如下:
@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; .... }
調(diào)用jpa的save方法,即使手動設(shè)置了id,手動設(shè)置的這個id也會被覆蓋。
要求
當(dāng)用戶手動設(shè)置了id,以用戶設(shè)置的id為準(zhǔn),否則使用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生成策略, 擴(kuò)展 {@link org.hibernate.id.UUIDGenerator} * 當(dāng)用戶設(shè)置了id,以用戶設(shè)置的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); } }
實(shí)體對象使用自定的策略
@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; .... }
現(xiàn)在可以手動設(shè)置id了
不設(shè)置則自動生成uuid
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用Java代碼實(shí)現(xiàn)RocketMQ的生產(chǎn)與消費(fèi)消息
這篇文章介紹一下其他的小組件以及使用Java代碼實(shí)現(xiàn)生產(chǎn)者對消息的生成,消費(fèi)者消費(fèi)消息等知識點(diǎn),并通過代碼示例介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-07-07Mybatis如何根據(jù)List批量查詢List結(jié)果
這篇文章主要介紹了Mybatis如何根據(jù)List批量查詢List結(jié)果,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03簡單說說Java SE、Java EE、Java ME三者之間的區(qū)別
本篇文章小編就為大家簡單說說Java SE、Java EE、Java ME三者之間的區(qū)別。需要的朋友可以過來參考下,希望對大家有所幫助2013-10-10java阿拉伯?dāng)?shù)字轉(zhuǎn)中文數(shù)字
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)阿拉伯?dāng)?shù)字轉(zhuǎn)換為中文數(shù)字,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-04-04關(guān)于文件上傳MultipartBody的使用方法
這篇文章主要介紹了關(guān)于文件上傳MultipartBody的使用方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06