diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java index c728051354..1a1ef41a30 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/internal/PropertyBinder.java @@ -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 ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/Fridge.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/Fridge.java index 8bca1751a9..3dddefef71 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/Fridge.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/Fridge.java @@ -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; + } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/JoinedManyToOneOwner.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/JoinedManyToOneOwner.java index 5ded56b4be..ac4076dd20 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/JoinedManyToOneOwner.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/JoinedManyToOneOwner.java @@ -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; + } } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/MetadataTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/MetadataTest.java index 7575c5335b..0658eedf5b 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/MetadataTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/metadata/MetadataTest.java @@ -121,6 +121,7 @@ public class MetadataTest { assertEquals(House.class, attr.getBindableJavaType()); final EntityType 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 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 attribute = entityType.getDeclaredAttribute("temperature"); assertNotNull(attribute); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/DefaultGeneratedValueTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/DefaultGeneratedValueTest.java index 52b6fabb75..99f1f2e203 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/DefaultGeneratedValueTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/generated/DefaultGeneratedValueTest.java @@ -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" ); + } + } }