HHH-17825 fix npe for single-column @UniqueConstraint

Note that HHH-17132 already attempted to fix the reported
problem, but the fix introduced a new bug, and NPE.
This commit is contained in:
Gavin King 2024-03-11 01:43:48 +01:00
parent 53301b530d
commit 4eb4327a54
3 changed files with 141 additions and 4 deletions

View File

@ -80,10 +80,21 @@ public class CreateTableUniqueDelegate extends AlterTableUniqueDelegate {
}
private static boolean isSingleColumnUnique(Table table, UniqueKey uniqueKey) {
return uniqueKey.getColumns().size() == 1
// Since columns are created on demand in IndexBinder.createColumn,
// we also have to check if the "real" column is unique to be safe
&& ( uniqueKey.getColumn( 0 ).isUnique() || table.getColumn( uniqueKey.getColumn( 0 ) ).isUnique() );
if ( uniqueKey.getColumns().size() == 1) {
// Since columns are created on demand in IndexBinder.createColumn,
// we also have to check if the "real" column is unique to be safe
final Column uniqueKeyColumn = uniqueKey.getColumn(0);
if ( uniqueKeyColumn.isUnique() ) {
return true;
}
else {
final Column column = table.getColumn( uniqueKeyColumn );
return column != null && column.isUnique();
}
}
else {
return false;
}
}
@Override

View File

@ -0,0 +1,61 @@
package org.hibernate.orm.test.schemaupdate.uniqueconstraint;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
@SessionFactory
@DomainModel(annotatedClasses = {MultiUniqueConstraintNameTest.MyEntity.class, MultiUniqueConstraintNameTest.MyOtherEntity.class})
public class MultiUniqueConstraintNameTest {
@Test void test(SessionFactoryScope scope) {
scope.getSessionFactory();
}
@Entity
@Table(name = "my_entity",
uniqueConstraints =
@UniqueConstraint(
name = "my_other_entity_id_unique",
columnNames = {"my_other_entity_id1","my_other_entity_id2"}
),
indexes = @Index(name = "some_long_index", columnList = "some_long"))
static class MyEntity {
@Id
long id1;
@Id
long id2;
@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "my_other_entity_id1")
@JoinColumn(name = "my_other_entity_id2")
private MyOtherEntity myOtherEntity;
@Column(name = "some_long")
private long someLong;
}
@Entity
@Table(name = "my_other_entity")
static class MyOtherEntity {
@Id
long id1;
@Id
long id2;
@Column(name = "some_string")
private String someString;
}
}

View File

@ -0,0 +1,65 @@
package org.hibernate.orm.test.schemaupdate.uniqueconstraint;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
@SessionFactory
@DomainModel(annotatedClasses = {UniqueConstraintNameTest.MyEntity.class, UniqueConstraintNameTest.MyOtherEntity.class})
@JiraKey("HHH-17825")
@JiraKey("HHH-17132")
public class UniqueConstraintNameTest {
@Test void test(SessionFactoryScope scope) {
scope.getSessionFactory();
}
@Entity
@Table(name = "my_entity",
uniqueConstraints =
@UniqueConstraint(
name = "my_other_entity_id_unique",
columnNames = "my_other_entity_id"
),
indexes = @Index(name = "some_long_index", columnList = "some_long"))
static class MyEntity {
@Id
@GeneratedValue
long id;
@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "my_other_entity_id",
updatable = false,
foreignKey = @ForeignKey(name = "FK_moe"))
private MyOtherEntity myOtherEntity;
@Column(name = "some_long")
private long someLong;
}
@Entity
@Table(name = "my_other_entity")
static class MyOtherEntity {
@Id
@GeneratedValue
long id;
@Column(name = "some_string")
private String someString;
}
}