Skip to content

Commit 01917bd

Browse files
committed
HHH-17017 Add test for issue
1 parent 65d4613 commit 01917bd

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package org.hibernate.orm.test.mapping.enumeratedvalue;
2+
3+
import org.hibernate.annotations.JdbcTypeCode;
4+
import org.hibernate.type.SqlTypes;
5+
6+
import org.hibernate.testing.orm.junit.DomainModel;
7+
import org.hibernate.testing.orm.junit.JiraKey;
8+
import org.hibernate.testing.orm.junit.SessionFactory;
9+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
10+
import org.junit.jupiter.api.Test;
11+
12+
import jakarta.persistence.Column;
13+
import jakarta.persistence.Entity;
14+
import jakarta.persistence.EntityManagerFactory;
15+
import jakarta.persistence.EnumType;
16+
import jakarta.persistence.Enumerated;
17+
import jakarta.persistence.EnumeratedValue;
18+
import jakarta.persistence.Id;
19+
import jakarta.persistence.Table;
20+
21+
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
22+
23+
@DomainModel(
24+
annotatedClasses = {
25+
EnumAndColumnDefinitionTest.TestEntity.class
26+
}
27+
)
28+
@SessionFactory
29+
@JiraKey("HHH-17017")
30+
public class EnumAndColumnDefinitionTest {
31+
32+
private EntityManagerFactory entityManagerFactory;
33+
34+
@Test
35+
public void testFind(SessionFactoryScope scope) {
36+
var id = 1L;
37+
var enumValue = MyEnum.A;
38+
var anotherEnumValue = AnotherMyEnum.B;
39+
var anotherEnumValue2 = AnotherMyEnum.A;
40+
scope.inTransaction(
41+
session ->
42+
session.persist( new TestEntity( id, enumValue, anotherEnumValue, anotherEnumValue2 ) )
43+
);
44+
45+
scope.inSession(
46+
session -> {
47+
var selectMyEnum = session.createNativeQuery(
48+
"select my_enum from test_entity",
49+
String.class
50+
)
51+
.getSingleResult();
52+
assertThat( selectMyEnum ).isEqualTo( "0" );
53+
54+
var selectAnotherMyEnum = session.createNativeQuery(
55+
"select another_my_enum from test_entity",
56+
String.class
57+
)
58+
.getSingleResult();
59+
assertThat( selectAnotherMyEnum ).isEqualTo( "1" );
60+
61+
var selectAnotherMyEnum2 = session.createNativeQuery(
62+
"select another_my_enum_2 from test_entity",
63+
String.class
64+
)
65+
.getSingleResult();
66+
// because the attribute is annotated with @JdbcTypeCode(SqlTypes.VARCHAR)
67+
// the enum string value has been saved
68+
assertThat( selectAnotherMyEnum2 ).isEqualTo( "A" );
69+
}
70+
);
71+
72+
scope.inSession(
73+
session -> {
74+
var testEntity = session.find( TestEntity.class, id );
75+
assertThat( testEntity.myEnum ).isEqualTo( enumValue );
76+
assertThat( testEntity.anotherMyEnum ).isEqualTo( anotherEnumValue );
77+
assertThat( testEntity.anotherMyEnum2 ).isEqualTo( anotherEnumValue2 );
78+
}
79+
);
80+
}
81+
82+
public enum MyEnum {
83+
A( 0 ),
84+
B( 1 );
85+
86+
@EnumeratedValue
87+
final int intValue;
88+
89+
MyEnum(int intValue) {
90+
this.intValue = intValue;
91+
}
92+
}
93+
94+
public enum AnotherMyEnum {
95+
A,
96+
B;
97+
}
98+
99+
@Entity(name = "TestEntity")
100+
@Table(name = "test_entity")
101+
public static class TestEntity {
102+
@Id
103+
Long id;
104+
105+
@Enumerated(value = EnumType.ORDINAL)
106+
@Column(name = "my_enum", columnDefinition = "VARCHAR(255) NOT NULL")
107+
/*
108+
annotating the enum with @EnumeratedValue permit to store the ordinal value
109+
and retrieve the correct enum value
110+
*/
111+
MyEnum myEnum;
112+
113+
@Enumerated(value = EnumType.ORDINAL)
114+
@Column(name = "another_my_enum", columnDefinition = "VARCHAR(255) NOT NULL")
115+
/*
116+
Without specifying the JdbcTypeCode Hibernate has no clue
117+
of the column being a VARCHAR and being the enum type an
118+
ordinal, a TinyIntJdbcType is used.
119+
To insert the enum value PreparedStatement#setByte() is used passing value 0
120+
while to retrieve the value PreparedStatement#getByte() is used
121+
and MySQL returns 48 causing the ArrayIndexOutOfBoundsException when trying
122+
to wrap the corresponding enum value.
123+
In previous version it worked probably because instead of TinyIntJdbcType an IntegerJdbcType
124+
has been used.
125+
126+
Using @JdbcTypeCode(SqlTypes.VARCHAR) the enum string value is save
127+
while using @JdbcTypeCode(SqlTypes.INTEGER) the ordinal values is saved
128+
129+
*/
130+
@JdbcTypeCode(SqlTypes.INTEGER)
131+
AnotherMyEnum anotherMyEnum;
132+
133+
@Enumerated(value = EnumType.ORDINAL)
134+
@Column(name = "another_my_enum_2", columnDefinition = "VARCHAR(255) NOT NULL")
135+
@JdbcTypeCode(SqlTypes.VARCHAR)
136+
AnotherMyEnum anotherMyEnum2;
137+
138+
String name;
139+
140+
public TestEntity() {
141+
142+
}
143+
144+
public TestEntity(Long id, MyEnum myEnum, AnotherMyEnum anotherMyEnum, AnotherMyEnum anotherMyEnum2) {
145+
this.id = id;
146+
this.myEnum = myEnum;
147+
this.anotherMyEnum = anotherMyEnum;
148+
this.anotherMyEnum2 = anotherMyEnum2;
149+
}
150+
}
151+
}

0 commit comments

Comments
 (0)