I am trying to use a custom ID generator in Spring-MVC boot application.
But instead of Spring creating an instance of ID generator, hibernate is creating it and
hence I am getting NullPointerException when I access autowired dependencies of ID generator.
**How can I tell hibernate not to create an instance of the Custom ID generator and allow Spring to do it?**
我尝试将@Component添加到自定义ID生成器类中,但是似乎休眠始终在创建实例。 我也经历过Configure custom hibernate id generator in spring context,但不明白如何解决此问题。 代码段如下:
实体类
实体类:这是我在策略自定义ID生成器(即要使用的KE_IDGenerator)中提到的模型类。
@Entity
@Table(name="TAB_Error")
public class KnownErrorDto {
@Id
@GenericGenerator(name="seq_id", strategy="x.x.x.x.IdGenerator.KE_IDGenerator"
)
@GeneratedValue(generator="seq_id")
@Column(name ="KEID")
String KEID;
}
_____________________________________________________________________________
道课 道:在此界面中,我提到了一种使用本机查询的方法,该方法给出下一个序列值。
public interface KnownErrorDaoInterface extends CrudRepository<KnownErrorDto,Integer> {
@Query(value = "SELECT TAB_Err_SEQ.nextval FROM dual", nativeQuery =
true)
int getNextSeqForKnownError();
}
_____________________________________________________________________________
自定义ID生成器类
自定义ID生成器:这是一个从Dao获取序列值并应返回自定义ID的类
public class KE_IDGenerator implements IdentifierGenerator {
@Autowired
KnownErrorDaoInterface knownErrorDaoInterface;
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object)
throws HibernateException {
String prefix = "KE";
int id=knownErrorDaoInterface.getNextSeqForKnownError();
String keId=null;
keId=prefix + StringUtils.leftPad("" + id,9, '0');
return keId;
}
}
_____________________________________________________________________________
我将遇到错误:
2019-07-21 20:11:11.165 ERROR 1900 --- [nio-8083-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException: null
at
x.x.x.x.IdGenerator.KE_IDGenerator.generate(KE_IDGenerator.java:27) ~[classes/:na]
我希望KE_IDGenerator使用KnownErrorDaoInterface提供的序列值生成自定义ID。但是,当我尝试访问KnownErrorDaoInterface时,我得到的是空指针。
答案 0 :(得分:0)
您的自定义Id生成器KE_IDGenerator
不是受Spring管理的bean,它将由spring管理,因此您不能在其中注入任何依赖项。 knownErrorDaoInterface
将始终为null。如果要使用现有序列表进行ID生成,可以像这样
@Entity
@Table(name="TAB_Error")
public class KnownErrorDto {
@Id
@GeneratedValue(generator="seq_name")
@SequenceGenerator(name="seq_name",sequenceName="seq_table",allocationSize=10)
@Column(name ="KEID")
String KEID;
}
答案 1 :(得分:0)
您可以在自定义生成器中使用 session
方法中的 generate
参数来执行本机语句。
这样做需要您编写自定义 SQL 语句并消除 Spring 和 Hibernate 处理它的舒适性,但它可以完成这项工作。
public class FimIdGenerator extends SequenceStyleGenerator {
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
// The object, that shall get a new ID is provided as `Object object`
// So feel free to cast it to your own entity
if(object instanceof FimEntity){
FimEntity entity = (FimEntity) object;
String createQuery = "CREATE SEQUENCE IF NOT EXISTS MY_CUSTOM_SEQENCE_NAME"
session.createSQLQuery(createQuery).executeUpdate();
String nextValQuery = "SELECT NEXTVAL('MY_CUSTOM_SEQENCE_NAME')";
BigInteger newId = (BigInteger) session.createSQLQuery(nextValQuery).getSingleResult();
return newId;
}else{
throw new HibernateException("Only entities of super type FimEntity are supported");
}
}
}
现在,这个例子使用了一个固定的序列名称,这不是我们都需要的,我们需要动态名称。所以我所做的是:
班级水平
private final static String CREATE_TEMPLATE = "CREATE SEQUENCE IF NOT EXISTS SEQ_%03d_%s START WITH 1";
private final static String NEXTVAL_TEMPLATE = "SELECT NEXTVAL('SEQ_%03d_%s');";
在 generate
方法级别(fimId
对象是我的实体的一方,我只是 getFimId()
在铸造的 object
上)
String createQuery = String.format(CREATE_TEMPLATE, fimId.getAppiid(), fimId.getEntityType());
session.createSQLQuery(createQuery).executeUpdate();
String nextValQuery = String.format(NEXTVAL_TEMPLATE, fimId.getAppiid(), fimId.getEntityType());
BigInteger newId = (BigInteger) session.createSQLQuery(nextValQuery).getSingleResult();
这样做会在运行时创建新的序列,例如“SEQ_001_tag”或租户 1 和实体类型标签或租户 16 和实体类型文档的“SEQ_016_document”。