Skip to content

Commit 0dd606a

Browse files
committed
HHH-19004 Fix regression of TenantId not being allowed on @EmbeddedId
1 parent 4b63f1a commit 0dd606a

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed

hibernate-core/src/main/java/org/hibernate/annotations/TenantId.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
* @author Gavin King
2727
*/
2828
@ValueGenerationType(generatedBy = TenantIdGeneration.class)
29+
@IdGeneratorType(TenantIdGeneration.class)
2930
@AttributeBinderType(binder = TenantIdBinder.class)
3031
@Target({METHOD, FIELD})
3132
@Retention(RUNTIME)

hibernate-core/src/main/java/org/hibernate/generator/internal/TenantIdGeneration.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.hibernate.generator.EventType;
1919
import org.hibernate.generator.EventTypeSets;
2020
import org.hibernate.generator.GeneratorCreationContext;
21+
import org.hibernate.id.factory.spi.CustomIdGeneratorCreationContext;
2122
import org.hibernate.type.descriptor.java.JavaType;
2223

2324
import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
@@ -33,6 +34,10 @@ public class TenantIdGeneration implements BeforeExecutionGenerator {
3334
private final String entityName;
3435
private final String propertyName;
3536

37+
public TenantIdGeneration(TenantId annotation, Member member, CustomIdGeneratorCreationContext context) {
38+
this(annotation, member, (GeneratorCreationContext) context);
39+
}
40+
3641
public TenantIdGeneration(TenantId annotation, Member member, GeneratorCreationContext context) {
3742
entityName = context.getPersistentClass() == null
3843
? member.getDeclaringClass().getName() //it's an attribute of an embeddable
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.orm.test.tenantid;
8+
9+
import org.hibernate.annotations.TenantId;
10+
import org.hibernate.boot.SessionFactoryBuilder;
11+
import org.hibernate.boot.spi.MetadataImplementor;
12+
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
13+
import org.hibernate.engine.spi.SessionFactoryImplementor;
14+
15+
import org.hibernate.testing.orm.junit.DomainModel;
16+
import org.hibernate.testing.orm.junit.Jira;
17+
import org.hibernate.testing.orm.junit.ServiceRegistry;
18+
import org.hibernate.testing.orm.junit.SessionFactory;
19+
import org.hibernate.testing.orm.junit.SessionFactoryProducer;
20+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
21+
import org.hibernate.testing.orm.junit.Setting;
22+
import org.junit.jupiter.api.AfterEach;
23+
import org.junit.jupiter.api.Test;
24+
25+
import jakarta.persistence.Column;
26+
import jakarta.persistence.Embeddable;
27+
import jakarta.persistence.EmbeddedId;
28+
import jakarta.persistence.Entity;
29+
import jakarta.persistence.EnumType;
30+
import jakarta.persistence.Enumerated;
31+
32+
import static org.hibernate.cfg.SchemaToolingSettings.JAKARTA_HBM2DDL_DATABASE_ACTION;
33+
import static org.junit.jupiter.api.Assertions.assertEquals;
34+
import static org.junit.jupiter.api.Assertions.assertNotNull;
35+
36+
@SessionFactory
37+
@DomainModel(annotatedClasses = { TenantIdGeneratedTest.DisplayIdBE.class })
38+
@ServiceRegistry(
39+
settings = {
40+
@Setting(name = JAKARTA_HBM2DDL_DATABASE_ACTION, value = "create-drop")
41+
}
42+
)
43+
@Jira("https://hibernate.atlassian.net/browse/HHH-19004")
44+
public class TenantIdGeneratedTest implements SessionFactoryProducer {
45+
46+
@AfterEach
47+
public void cleanup(SessionFactoryScope scope) {
48+
scope.getSessionFactory().getSchemaManager().truncateMappedObjects();
49+
}
50+
51+
@Override
52+
public SessionFactoryImplementor produceSessionFactory(MetadataImplementor model) {
53+
final SessionFactoryBuilder sessionFactoryBuilder = model.getSessionFactoryBuilder();
54+
sessionFactoryBuilder.applyCurrentTenantIdentifierResolver( new CurrentTenantIdentifierResolver<Long>() {
55+
@Override
56+
public Long resolveCurrentTenantIdentifier() {
57+
return 0L;
58+
}
59+
@Override
60+
public boolean validateExistingCurrentSessions() {
61+
return false;
62+
}
63+
} );
64+
return (SessionFactoryImplementor) sessionFactoryBuilder.build();
65+
}
66+
67+
@Test
68+
public void test(SessionFactoryScope scope) {
69+
scope.inTransaction( session -> {
70+
session.persist(new DisplayIdBE( new DisplayIdKeyBE( null, DisplayIdType.TYPE1 ), 1L ));
71+
} );
72+
scope.inTransaction( session -> {
73+
assertNotNull( session.find( DisplayIdBE.class, new DisplayIdKeyBE( 0L, DisplayIdType.TYPE1 ) ) );
74+
assertEquals( 1, session.createQuery("from DisplayIdBE", DisplayIdBE.class).getResultList().size() );
75+
} );
76+
}
77+
78+
@Entity(name = "DisplayIdBE")
79+
public static class DisplayIdBE {
80+
81+
@EmbeddedId
82+
private DisplayIdKeyBE id;
83+
84+
@Column(name = "display_id_value", nullable = false)
85+
private long displayIdValue;
86+
87+
protected DisplayIdBE() {
88+
}
89+
90+
public DisplayIdBE(DisplayIdKeyBE id, long displayIdValue) {
91+
this.id = id;
92+
this.displayIdValue = displayIdValue;
93+
}
94+
}
95+
96+
public enum DisplayIdType {
97+
TYPE1,
98+
TYPE2
99+
}
100+
101+
@Embeddable
102+
public static class DisplayIdKeyBE {
103+
104+
@TenantId
105+
@Column(name = "tenant_id", nullable = false)
106+
private Long tenantId;
107+
108+
@Column(name = "type", nullable = false)
109+
@Enumerated(EnumType.STRING)
110+
private DisplayIdType type;
111+
112+
protected DisplayIdKeyBE() {}
113+
114+
public DisplayIdKeyBE(Long tenantId, DisplayIdType type) {
115+
this.tenantId = tenantId;
116+
this.type = type;
117+
}
118+
}
119+
120+
}

0 commit comments

Comments
 (0)