Skip to content

Commit 8cf34b5

Browse files
cigalybeikov
authored andcommitted
HHH-18787 Test case
1 parent 10794a4 commit 8cf34b5

File tree

5 files changed

+265
-0
lines changed

5 files changed

+265
-0
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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.type.contributor.usertype.hhh18787;
8+
9+
/**
10+
* Simple object holding some properties
11+
*/
12+
public class CustomData {
13+
private String text;
14+
private Long number;
15+
16+
public CustomData(String text, Long number) {
17+
this.text = text;
18+
this.number = number;
19+
}
20+
21+
public String getText() {
22+
return text;
23+
}
24+
25+
public void setText(String text) {
26+
this.text = text;
27+
}
28+
29+
public Long getNumber() {
30+
return number;
31+
}
32+
33+
public void setNumber(Long number) {
34+
this.number = number;
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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.type.contributor.usertype.hhh18787;
8+
9+
import org.hibernate.engine.spi.SharedSessionContractImplementor;
10+
import org.hibernate.type.SqlTypes;
11+
import org.hibernate.usertype.UserType;
12+
13+
import java.io.Serializable;
14+
import java.sql.PreparedStatement;
15+
import java.sql.ResultSet;
16+
import java.sql.SQLException;
17+
import java.sql.Types;
18+
import java.util.Arrays;
19+
import java.util.stream.Collectors;
20+
import java.util.stream.Stream;
21+
22+
/**
23+
* Custom type implementing {@link UserType} so <code>CustomData[]</code> can be converted.
24+
*/
25+
public class CustomDataType implements UserType<CustomData[]> {
26+
27+
public static final CustomDataType INSTANCE = new CustomDataType();
28+
29+
@Override
30+
public int getSqlType() {
31+
return SqlTypes.VARCHAR;
32+
}
33+
34+
@Override
35+
public Class<CustomData[]> returnedClass() {
36+
return CustomData[].class;
37+
}
38+
39+
@Override
40+
public boolean equals(CustomData[] x, CustomData[] y) {
41+
return Arrays.equals(x, y);
42+
}
43+
44+
@Override
45+
public int hashCode(CustomData[] x) {
46+
return Arrays.hashCode(x);
47+
}
48+
49+
@Override
50+
public CustomData[] nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session,
51+
Object owner) throws SQLException {
52+
53+
final var customDataStr = rs.getString(position);
54+
return rs.wasNull() ? new CustomData[0] : parseDataFromString(customDataStr);
55+
}
56+
57+
@Override
58+
public void nullSafeSet(PreparedStatement st, CustomData[] value, int index,
59+
SharedSessionContractImplementor session) throws SQLException {
60+
61+
if (value == null || value.length == 0) {
62+
st.setNull(index, Types.VARCHAR);
63+
}
64+
else {
65+
final var str =
66+
Stream.of(value).map(u -> String.format("%s|%s", u.getText(), u.getNumber())).collect(Collectors.joining(","));
67+
68+
st.setString(index, str);
69+
}
70+
}
71+
72+
@Override
73+
public CustomData[] deepCopy(CustomData[] value) {
74+
return Arrays.copyOf(value, value.length);
75+
}
76+
77+
@Override
78+
public boolean isMutable() {
79+
return true;
80+
}
81+
82+
@Override
83+
public Serializable disassemble(CustomData[] value) {
84+
return deepCopy(value);
85+
}
86+
87+
@Override
88+
public CustomData[] assemble(Serializable cached, Object owner) {
89+
return deepCopy((CustomData[]) cached);
90+
}
91+
92+
private CustomData[] parseDataFromString(String value) {
93+
return Arrays.stream(value.split(",")).map(singleValue -> {
94+
final var params = singleValue.split("\\|");
95+
return new CustomData(params[0], Long.parseLong(params[1]));
96+
}).toArray(CustomData[]::new);
97+
}
98+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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.type.contributor.usertype.hhh18787;
8+
9+
import jakarta.persistence.Column;
10+
import jakarta.persistence.Entity;
11+
import jakarta.persistence.GeneratedValue;
12+
import jakarta.persistence.Id;
13+
import jakarta.persistence.Table;
14+
15+
/**
16+
* Some entity, important is the property <code>customData</code>.
17+
*/
18+
@Entity
19+
@Table(name = "whatever")
20+
public class SomeEntity {
21+
@Id
22+
@GeneratedValue
23+
private Long id;
24+
25+
@Column
26+
private CustomData[] customData;
27+
28+
public SomeEntity() {
29+
}
30+
31+
public SomeEntity(CustomData[] customData) {
32+
this.customData = customData;
33+
}
34+
35+
public Long getId() {
36+
return id;
37+
}
38+
39+
public void setId(Long id) {
40+
this.id = id;
41+
}
42+
43+
public CustomData[] getCustomData() {
44+
return customData;
45+
}
46+
47+
public void setCustomData(CustomData[] custom) {
48+
this.customData = custom;
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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.type.contributor.usertype.hhh18787;
8+
9+
import org.hibernate.boot.model.TypeContributions;
10+
import org.hibernate.boot.model.TypeContributor;
11+
import org.hibernate.service.ServiceRegistry;
12+
13+
/**
14+
* Registering custom user type {@link CustomDataType}.
15+
*/
16+
public class TypesContributor implements TypeContributor {
17+
18+
@Override
19+
public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
20+
typeContributions.contributeType(CustomDataType.INSTANCE);
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
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.type.contributor.usertype.hhh18787;
8+
9+
import org.hibernate.testing.orm.junit.DomainModel;
10+
import org.hibernate.testing.orm.junit.JiraKey;
11+
import org.hibernate.testing.orm.junit.SessionFactory;
12+
import org.hibernate.testing.orm.junit.SessionFactoryScope;
13+
import org.junit.jupiter.api.Test;
14+
15+
import static org.junit.jupiter.api.Assertions.assertEquals;
16+
import static org.junit.jupiter.api.Assertions.assertNotNull;
17+
18+
@DomainModel(
19+
annotatedClasses = SomeEntity.class,
20+
typeContributors = TypesContributor.class
21+
)
22+
@SessionFactory
23+
@JiraKey( "HHH-18787" )
24+
class UserTypeNotRecognisedTestCase {
25+
26+
@Test
27+
void customUserTypeWithTypeContributorRegistrationTest(SessionFactoryScope scope) {
28+
final var data = new CustomData( "whatever", 1L );
29+
scope.inTransaction( em -> {
30+
// creating some data, flushing and clearing context
31+
em.merge( new SomeEntity( new CustomData[] {data} ) );
32+
} );
33+
34+
scope.inSession( em -> {
35+
// getting the data
36+
final var query = em.createQuery( "select s from SomeEntity s where id is not null", SomeEntity.class );
37+
final var resultList = query.getResultList();
38+
39+
// single result should be present
40+
assertNotNull( resultList );
41+
assertEquals( 1, resultList.size() );
42+
43+
// the entity shouldn't be null
44+
final var entity = resultList.get( 0 );
45+
assertNotNull( entity );
46+
47+
// custom data array shouldn't be null and there should be single object present
48+
final var customData = entity.getCustomData();
49+
assertNotNull( customData );
50+
assertEquals( 1, customData.length );
51+
52+
// custom data object shouldn't be null and all fields should be set with correct values
53+
final var singleCustomData = customData[0];
54+
assertNotNull( singleCustomData );
55+
assertEquals( data.getText(), singleCustomData.getText() );
56+
assertEquals( data.getNumber(), singleCustomData.getNumber() );
57+
} );
58+
}
59+
}

0 commit comments

Comments
 (0)