HHH-16359 Make attributes non-optional which have only non-nullable columns

This commit is contained in:
Christian Beikov 2023-03-24 19:05:57 +01:00
parent 07ae0ddc3e
commit 7f7e4b5f6a
5 changed files with 45 additions and 2 deletions

View File

@ -453,10 +453,15 @@ public class PropertyBinder {
private void handleOptional(Property property) {
if ( this.property != null ) {
property.setOptional( !isId && isOptional( this.property ) );
property.setOptional( !isId && isOptional( this.property ) && isNullable( property ) );
}
}
private static boolean isNullable(Property property) {
final Value value = property.getValue();
return value instanceof org.hibernate.mapping.OneToMany || value.isNullable();
}
private void handleNaturalId(Property property) {
if ( this.property != null && entityBinder != null ) {
final NaturalId naturalId = this.property.getAnnotation( NaturalId.class );

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.orm.test.jpa.metadata;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
@ -18,6 +19,7 @@ public class Fridge {
private Long id;
private String brand;
private int temperature;
private Integer height;
//dimensions
@Id
@ -46,5 +48,14 @@ public class Fridge {
public void setTemperature(int temperature) {
this.temperature = temperature;
}
@Column(nullable = false)
public Integer getHeight() {
return height;
}
public void setHeight(Integer height) {
this.height = height;
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.orm.test.jpa.metadata;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToOne;
@ -21,6 +22,7 @@ import jakarta.persistence.ManyToOne;
public class JoinedManyToOneOwner {
private Long id;
private House house;
private House house2;
@Id
public Long getId() {
@ -39,4 +41,14 @@ public class JoinedManyToOneOwner {
public void setHouse(House house) {
this.house = house;
}
@ManyToOne
@JoinColumn(name = "house2", nullable = false)
public House getHouse2() {
return house2;
}
public void setHouse2(House house2) {
this.house2 = house2;
}
}

View File

@ -121,6 +121,7 @@ public class MetadataTest {
assertEquals(House.class, attr.getBindableJavaType());
final EntityType<House> houseType = scope.getEntityManagerFactory().getMetamodel().entity(House.class);
assertEquals(houseType.getBindableJavaType(), attr.getBindableJavaType());
assertFalse(entityType.getDeclaredSingularAttribute("house2").isOptional());
}
@Test
@ -158,7 +159,7 @@ public class MetadataTest {
assertFalse(fridgeType.hasVersionAttribute());
assertEquals(Type.PersistenceType.ENTITY, fridgeType.getPersistenceType());
assertEquals(3, fridgeType.getDeclaredAttributes().size());
assertEquals(4, fridgeType.getDeclaredAttributes().size());
final EntityType<House> houseType = scope.getEntityManagerFactory().getMetamodel().entity(House.class);
assertEquals("House", houseType.getName());
@ -231,6 +232,7 @@ public class MetadataTest {
assertFalse(singularAttribute.isId());
assertFalse(singularAttribute.isOptional());
assertFalse(entityType.getDeclaredSingularAttribute("brand", String.class).isOptional());
assertFalse(entityType.getDeclaredSingularAttribute("height", Integer.class).isOptional());
assertEquals(Type.PersistenceType.BASIC, singularAttribute.getType().getPersistenceType());
final Attribute<? super Fridge, ?> attribute = entityType.getDeclaredAttribute("temperature");
assertNotNull(attribute);

View File

@ -25,6 +25,7 @@ import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.HibernateError;
import org.hibernate.Session;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.CreationTimestamp;
@ -152,6 +153,9 @@ public class DefaultGeneratedValueTest {
assertNotNull( created.vmCreatedSqlTimestamp );
assertNotNull( created.updated );
//We need to wait a little to make sure the timestamps produced are different
waitALittle();
scope.inTransaction( (s) -> {
final TheEntity theEntity = s.get( TheEntity.class, 1 );
theEntity.lastName = "Smith";
@ -255,4 +259,13 @@ public class DefaultGeneratedValueTest {
return "Bob";
}
}
private static void waitALittle() {
try {
Thread.sleep( 10 );
}
catch (InterruptedException e) {
throw new HibernateError( "Unexpected wakeup from test sleep" );
}
}
}