public class SequenceControlNumber extends SequenceGenerator {
private static final Logger log =
LoggerFactory.getLogger(SequenceGenerator.class);
@Override
public Serializable generate(SessionImplementor session, Object obj) {
Connection connection = session.connection();
try {
PreparedStatement st = connection.prepareStatement
("SELECT nextval ('sequencecontrolnumber') as nextval");
try {
ResultSet rs = st.executeQuery();
try {
rs.next();
int currentVall = rs.getInt("sequencecontrolnumber");
int result = 0;
if(currentVall <255){
result = currentVall +1;
}
if ( log.isDebugEnabled() ) {
log.debug("Sequence identifier generated: " + result);
}
return result;
}
finally {
rs.close();
}
}
finally {
session.getBatcher().closeStatement(st);
}
}
catch (SQLException sqle) {
throw JDBCExceptionHelper.convert(
session.getFactory().getSQLExceptionConverter(),
sqle,"could not get next sequence value");
}
}
}
在我的模型类中,这是我的注释:
@GenericGenerator(name="seq_id",
strategy="br.com.otgmobile.service.dao.SequenceControlNumber")
@GeneratedValue(generator="seq_id")
@Column(name="sequencecontrolnumber",unique=false, nullable=false)
private Integer sequenceControlNumber;
但我不断获得属性值异常。
javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value: br.com.otgmobile.model.niagarahw06.ComandoNiagaraHw06.sequenceControlNumber
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1179)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1112)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1118)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:618)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
at $Proxy33.persist(Unknown Source)
at br.com.otgmobile.service.dao.ComandoNiagaraHw06DAO.add(ComandoNiagaraHw06DAO.java:57)
at br.com.otgmobile.service.dao.ComandoNiagaraHw06DAO$$FastClassByCGLIB$$e19cf51d.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at br.com.otgmobile.service.dao.ComandoNiagaraHw06DAO$$EnhancerByCGLIB$$69ccb4e4.add(<generated>)
at br.com.otgmobile.server.NiagaraSocketManager.testPersistComandos(NiagaraSocketManager.java:100)
at br.com.otgmobile.server.NiagaraSocketManager.start(NiagaraSocketManager.java:45)
at br.com.otgmobile.server.NiagaraDaemon.run(NiagaraDaemon.java:25)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: br.com.otgmobile.model.niagarahw06.ComandoNiagaraHw06.sequenceControlNumber
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:101)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:313)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:69)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:179)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:800)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:774)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:778)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:612)
答案 0 :(得分:2)
对于非id字段的自定义序列生成器,可以将@GeneratorType与ValueGenerator类实现一起使用。例如:
import org.hibernate.annotations.GeneratorType
@GeneratorType(type = CustomGenerator.class, when = GenerationTime.INSERT)
@Column(name = "CUSTOM_COLUMN", unique = true, nullable = false, updatable = false, lenght = 64)
private String custom;
public class CustomGenerator extends ValueGenerator<String> {
private static final String TODAY_EXAMPLE_QUERY = "from Example where createDate>:start and createDate<:end order by createDate desc";
private static final String START_PARAMETER = "start";
private static final String END_PARAMETER = "end";
private static final String NEXTVAL_QUERY = "select EXAMPLE_SEQ.nextval from dual";
private final SimpleDateFormat dataFormat = new SimpleDateFormat("yyyyMMdd");
@Override
public String generateValue(Session session, Object owner) {
Date now = new Date();
Query<Example> todayQuery = session.createQuery(TODAY_EXAMPLE_QUERY, Example.class);
query.setParameter(START_PARAMETER, start(now));
query.setParameter(END_PARAMETER, end(now));
Example lastExample = todayQuery.setMaxResult(1).setHibernateFlushMode(COMMIT).uniqueResult();
NativeQuery nextvalQuery = session.createSQLQuery(NEXTVAL_QUERY);
Number nextvalValue = nextvalQuery.setFlushMode(COMMIT).uniqueResult();
return dataFormat.format(now) + someParameter(lastExample) + nextvalValue.longValue();
}
}
答案 1 :(得分:1)
检查result
类中的generate方法返回的SequenceControlNumber
的值。
BTW在此SO问题中检查此回复:Hibernate JPA Sequence (non-Id)
答案 2 :(得分:1)
@GeneratedValue
注释不是Hibernate将作为列信息的一部分处理的内容。它必须与@Id
注释一起使用。它只是说当有id时如何生成id。
你有几个选项可以完成你想要的东西,但是没有一个像你所写的那样只使用注释那么优雅。这些建议有其优点和缺点(数据库可移植性,复杂性,实体管理器与会话等),但有些想法是:
AnnotationConfiguration
。此侦听器将查找需要此功能的实体类型,并将获取/分配下一个序列值insertable = false, updatable = false
答案 3 :(得分:1)
这至少在Postgres中对我有用
@Generated(GenerationTime.INSERT)
@Column(name = "internal_id", columnDefinition = "serial", updatable = false)
private int internalId;
答案 4 :(得分:0)
我刚遇到类似的问题,需要创建序列并将其附加到不是主键的字段上。
我一直在努力使用@GeneratedValue
和@SequenceGenerator
注释,因为正如Web上所述:@GeneratedValue
只能与Hibernate实体字段上的@Id注释一起使用。
这告诉Hibernate不要在意该字段是否为空,它将在插入数据库时进行管理。但是这里的Hibernate总是抛出Exception,因为在字段上GeneratedValue被忽略了。
因此解决方案很简单:只需用@Generated(GenerationTime.INSERT)
替换此注释,然后将columnDefinition = "serial"
添加到您的@Column(name = "huhu", columnDefinition = "serial", updatable = false, ...)
通常,如果您首先创建了附加到数据库中字段的正确序列,现在它应该可以正常工作。