HHH-11096 - @CreationTimestamp doesn't works with @Column(nullable=false)

This commit is contained in:
Vlad Mihalcea 2018-10-31 20:31:23 +02:00
parent d39d456614
commit 71af989f60
5 changed files with 228 additions and 4 deletions

View File

@ -11,14 +11,13 @@ import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.PropertyValueException;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadingActions;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.InMemoryValueGenerationStrategy;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
/**
@ -95,10 +94,14 @@ public final class Nullability {
? persister.getPropertyInsertability()
: persister.getPropertyUpdateability();
final Type[] propertyTypes = persister.getPropertyTypes();
final InMemoryValueGenerationStrategy[] inMemoryValueGenerationStrategies =
persister.getEntityMetamodel().getInMemoryValueGenerationStrategies();
for ( int i = 0; i < values.length; i++ ) {
if ( checkability[i] && values[i]!= LazyPropertyInitializer.UNFETCHED_PROPERTY ) {
if ( checkability[i] &&
values[i] != LazyPropertyInitializer.UNFETCHED_PROPERTY &&
GenerationTiming.NEVER == inMemoryValueGenerationStrategies[i].getGenerationTiming() ) {
final Object value = values[i];
if ( !nullability[i] && value == null ) {
//check basic level one nullablilty

View File

@ -0,0 +1,132 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.annotations;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.Generated;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.ValueGenerationType;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.tuple.AnnotationValueGeneration;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.ValueGenerator;
import org.hibernate.testing.TestForIssue;
import org.junit.Assert;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Vlad Mihalcea
*/
@TestForIssue( jiraKey = "HHH-11096" )
public class DatabaseCreationTimestampNullableColumnTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{
Person.class
};
}
@Entity(name = "Person")
public class Person {
@Id
@GeneratedValue
private Long id;
@NaturalId
private String name;
@Column(nullable = false)
@FunctionCreationTimestamp
private Date creationDate;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
}
@ValueGenerationType(generatedBy = FunctionCreationValueGeneration.class)
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionCreationTimestamp {}
public static class FunctionCreationValueGeneration
implements AnnotationValueGeneration<FunctionCreationTimestamp> {
@Override
public void initialize(FunctionCreationTimestamp annotation, Class<?> propertyType) {
}
/**
* Generate value on INSERT
* @return when to generate the value
*/
public GenerationTiming getGenerationTiming() {
return GenerationTiming.INSERT;
}
/**
* Returns null because the value is generated by the database.
* @return null
*/
public ValueGenerator<?> getValueGenerator() {
return null;
}
/**
* Returns true because the value is generated by the database.
* @return true
*/
public boolean referenceColumnInSql() {
return true;
}
/**
* Returns the database-generated value
* @return database-generated value
*/
public String getDatabaseGeneratedReferencedColumnValue() {
return "current_timestamp";
}
}
@Test
public void generatesCurrentTimestamp() {
doInJPA(this::entityManagerFactory, entityManager -> {
Person person = new Person();
person.setName("John Doe");
entityManager.persist(person);
entityManager.flush();
Assert.assertNotNull(person.getCreationDate());
});
}
}

View File

@ -0,0 +1,81 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.annotations;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.NaturalId;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Assert;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
/**
* @author Vlad Mihalcea
*/
@TestForIssue( jiraKey = "HHH-11096" )
public class InMemoryCreationTimestampNullableColumnTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[]{
Person.class
};
}
@Entity(name = "Person")
public class Person {
@Id
@GeneratedValue
private Long id;
@NaturalId
private String name;
@Column(nullable = false)
@CreationTimestamp
private Date creationDate;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
}
@Test
public void generatesCurrentTimestamp() {
doInJPA(this::entityManagerFactory, entityManager -> {
Person person = new Person();
person.setName("John Doe");
entityManager.persist(person);
entityManager.flush();
Assert.assertNotNull(person.getCreationDate());
});
}
}

View File

@ -1,3 +1,9 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.annotations;
import org.hibernate.annotations.UpdateTimestamp;

View File

@ -14,6 +14,8 @@
<id type="string" name="id" column="id_" length="64" unsaved-value="null" access="field">
<generator class="uuid.hex"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>