Skip to content

Commit 6584eb3

Browse files
stringintechmbellade
authored andcommitted
HHH-18764 Fix incorrect type resolution in ManyToOneType dirty check
1 parent 5328e83 commit 6584eb3

File tree

2 files changed

+221
-2
lines changed

2 files changed

+221
-2
lines changed

hibernate-core/src/main/java/org/hibernate/type/ManyToOneType.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ public boolean isDirty(
249249
}
250250
Object oldid = getIdentifier( old, session );
251251
Object newid = getIdentifier( current, session );
252-
return getIdentifierType( session ).isDirty( oldid, newid, session );
252+
return getIdentifierOrUniqueKeyType( session.getFactory() ).isDirty( oldid, newid, session );
253253
}
254254

255255
@Override
@@ -267,7 +267,7 @@ public boolean isDirty(
267267
}
268268
Object oldid = getIdentifier( old, session );
269269
Object newid = getIdentifier( current, session );
270-
return getIdentifierType( session ).isDirty( oldid, newid, checkable, session );
270+
return getIdentifierOrUniqueKeyType( session.getFactory() ).isDirty( oldid, newid, checkable, session );
271271
}
272272

273273
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
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.associations;
8+
9+
import java.io.Serializable;
10+
import java.sql.PreparedStatement;
11+
import java.sql.ResultSet;
12+
import java.sql.SQLException;
13+
import java.sql.Types;
14+
import java.util.Objects;
15+
16+
import org.hibernate.HibernateException;
17+
import org.hibernate.annotations.NaturalId;
18+
import org.hibernate.annotations.Type;
19+
import org.hibernate.engine.spi.SharedSessionContractImplementor;
20+
import org.hibernate.usertype.EnhancedUserType;
21+
22+
import org.hibernate.testing.orm.junit.DomainModel;
23+
import org.hibernate.testing.orm.junit.JiraKey;
24+
import org.hibernate.testing.orm.junit.SessionFactory;
25+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
26+
import org.junit.jupiter.api.Test;
27+
28+
import jakarta.persistence.Entity;
29+
import jakarta.persistence.FetchType;
30+
import jakarta.persistence.GeneratedValue;
31+
import jakarta.persistence.Id;
32+
import jakarta.persistence.JoinColumn;
33+
import jakarta.persistence.ManyToOne;
34+
35+
/**
36+
* @author Kowsar Atazadeh
37+
*/
38+
@SessionFactory
39+
@DomainModel(annotatedClasses =
40+
{
41+
ManyToOneUniqueKeyReferenceWithCustomIdTest.Phone.class,
42+
ManyToOneUniqueKeyReferenceWithCustomIdTest.User.class
43+
})
44+
@JiraKey("HHH-18764")
45+
public class ManyToOneUniqueKeyReferenceWithCustomIdTest {
46+
47+
@Test
48+
void test(SessionFactoryScope scope) {
49+
scope.inTransaction( session -> {
50+
Phone phone = new Phone();
51+
52+
User user1 = new User( new CustomId( "u1" ), "Kowsar" );
53+
session.persist( user1 );
54+
phone.setUser( user1 );
55+
session.persist( phone );
56+
57+
User user2 = new User( new CustomId( "u2" ), "Someone" );
58+
session.persist( user2 );
59+
phone.setUser( user2 );
60+
session.persist( phone );
61+
} );
62+
}
63+
64+
@Entity(name = "Phone")
65+
static class Phone {
66+
@Id
67+
@GeneratedValue
68+
Long id;
69+
70+
@ManyToOne(fetch = FetchType.LAZY)
71+
@JoinColumn(referencedColumnName = "name", nullable = false)
72+
User user;
73+
74+
public Long getId() {
75+
return id;
76+
}
77+
78+
public void setId(Long id) {
79+
this.id = id;
80+
}
81+
82+
public User getUser() {
83+
return user;
84+
}
85+
86+
public void setUser(User user) {
87+
this.user = user;
88+
}
89+
}
90+
91+
@Entity(name = "_User")
92+
static class User {
93+
@Id
94+
@Type(CustomIdType.class)
95+
CustomId id;
96+
97+
@NaturalId
98+
String name;
99+
100+
public User() {
101+
}
102+
103+
public User(CustomId id, String name) {
104+
this.id = id;
105+
this.name = name;
106+
}
107+
108+
public String getName() {
109+
return name;
110+
}
111+
112+
public void setName(String name) {
113+
this.name = name;
114+
}
115+
116+
public CustomId getId() {
117+
return id;
118+
}
119+
120+
public void setId(CustomId id) {
121+
this.id = id;
122+
}
123+
}
124+
125+
static class CustomIdType implements EnhancedUserType<CustomId> {
126+
@Override
127+
public String toSqlLiteral(CustomId value) {
128+
return "'" + value.toString() + "'";
129+
}
130+
131+
@Override
132+
public String toString(CustomId value) throws HibernateException {
133+
return value.toString();
134+
}
135+
136+
@Override
137+
public void nullSafeSet(
138+
PreparedStatement st, CustomId value, int position,
139+
SharedSessionContractImplementor session) throws SQLException {
140+
st.setObject( position, value.toString(), getSqlType() );
141+
}
142+
143+
@Override
144+
public CustomId nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner)
145+
throws SQLException {
146+
String idValue = rs.getString( position );
147+
return idValue != null ? fromStringValue( idValue ) : null;
148+
}
149+
150+
@Override
151+
public CustomId fromStringValue(CharSequence sequence) throws HibernateException {
152+
return new CustomId( sequence.toString() );
153+
}
154+
155+
@Override
156+
public int getSqlType() {
157+
return Types.VARCHAR;
158+
}
159+
160+
@Override
161+
public Class<CustomId> returnedClass() {
162+
return CustomId.class;
163+
}
164+
165+
@Override
166+
public CustomId deepCopy(CustomId value) {
167+
return new CustomId( value.getId() );
168+
}
169+
170+
@Override
171+
public boolean isMutable() {
172+
return false;
173+
}
174+
175+
@Override
176+
public Serializable disassemble(CustomId value) {
177+
return value;
178+
}
179+
180+
@Override
181+
public CustomId assemble(Serializable cached, Object owner) {
182+
return (CustomId) cached;
183+
}
184+
185+
@Override
186+
public boolean equals(CustomId x, CustomId y) {
187+
return Objects.equals( x, y );
188+
}
189+
190+
@Override
191+
public int hashCode(CustomId x) {
192+
return x != null ? x.hashCode() : 0;
193+
}
194+
}
195+
196+
static class CustomId implements Serializable {
197+
private String id;
198+
199+
public CustomId() {
200+
}
201+
202+
public CustomId(String id) {
203+
this.id = id;
204+
}
205+
206+
@Override
207+
public String toString() {
208+
return id;
209+
}
210+
211+
public String getId() {
212+
return id;
213+
}
214+
215+
public void setId(String id) {
216+
this.id = id;
217+
}
218+
}
219+
}

0 commit comments

Comments
 (0)