Skip to content

Commit f2ac87f

Browse files
committed
Implement support for CompositeUserType and re-enable tests that make use of it
1 parent 40bcb97 commit f2ac87f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1153
-193
lines changed

documentation/src/test/java/org/hibernate/userguide/mapping/basic/ColumnTransformerTest.java

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,16 @@
1111
import java.util.Locale;
1212

1313
import org.hibernate.annotations.ColumnTransformer;
14+
import org.hibernate.annotations.CompositeType;
1415
import org.hibernate.dialect.H2Dialect;
1516
import org.hibernate.orm.test.jpa.BaseEntityManagerFunctionalTestCase;
1617

1718
import org.hibernate.testing.RequiresDialect;
1819
import org.junit.Test;
1920

21+
import jakarta.persistence.AttributeOverride;
22+
import jakarta.persistence.AttributeOverrides;
23+
import jakarta.persistence.Column;
2024
import jakarta.persistence.Entity;
2125
import jakarta.persistence.Id;
2226

@@ -43,15 +47,14 @@ public void testLifecycle() {
4347
//tag::basic-datetime-temporal-date-persist-example[]
4448
Savings savings = new Savings();
4549
savings.setId(1L);
46-
savings.setCurrency(Currency.getInstance(Locale.US));
47-
savings.setAmount(BigDecimal.TEN);
50+
savings.setWallet(new MonetaryAmount(BigDecimal.TEN, Currency.getInstance(Locale.US)));
4851
entityManager.persist(savings);
4952
});
5053

5154
doInJPA(this::entityManagerFactory, entityManager -> {
5255
Savings savings = entityManager.find(Savings.class, 1L);
53-
assertEquals(10, savings.getAmount().intValue());
54-
assertEquals(Currency.getInstance(Locale.US), savings.getCurrency());
56+
assertEquals(10, savings.getWallet().getAmount().intValue());
57+
assertEquals(Currency.getInstance(Locale.US), savings.getWallet().getCurrency());
5558
});
5659
//end::mapping-column-read-and-write-composite-type-persistence-example[]
5760
}
@@ -63,12 +66,17 @@ public static class Savings {
6366
@Id
6467
private Long id;
6568

69+
@CompositeType(MonetaryAmountUserType.class)
70+
@AttributeOverrides({
71+
@AttributeOverride(name = "amount", column = @Column(name = "money")),
72+
@AttributeOverride(name = "currency", column = @Column(name = "currency"))
73+
})
6674
@ColumnTransformer(
67-
read = "amount / 100",
75+
forColumn = "money",
76+
read = "money / 100",
6877
write = "? * 100"
6978
)
70-
private BigDecimal amount;
71-
private Currency currency;
79+
private MonetaryAmount wallet;
7280

7381
//Getters and setters omitted for brevity
7482

@@ -81,20 +89,12 @@ public void setId(Long id) {
8189
this.id = id;
8290
}
8391

84-
public BigDecimal getAmount() {
85-
return amount;
92+
public MonetaryAmount getWallet() {
93+
return wallet;
8694
}
8795

88-
public void setAmount(BigDecimal amount) {
89-
this.amount = amount;
90-
}
91-
92-
public Currency getCurrency() {
93-
return currency;
94-
}
95-
96-
public void setCurrency(Currency currency) {
97-
this.currency = currency;
96+
public void setWallet(MonetaryAmount wallet) {
97+
this.wallet = wallet;
9898
}
9999

100100

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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.userguide.mapping.basic;
8+
9+
import java.io.Serializable;
10+
import java.math.BigDecimal;
11+
import java.util.Currency;
12+
import java.util.function.Supplier;
13+
14+
import org.hibernate.HibernateException;
15+
import org.hibernate.engine.spi.SessionFactoryImplementor;
16+
import org.hibernate.usertype.CompositeUserType;
17+
18+
/**
19+
* @author Emmanuel Bernard
20+
*/
21+
public class MonetaryAmountUserType implements CompositeUserType<MonetaryAmount> {
22+
23+
@Override
24+
public Object getPropertyValue(MonetaryAmount component, int property) throws HibernateException {
25+
switch ( property ) {
26+
case 0:
27+
return component.getAmount();
28+
case 1:
29+
return component.getCurrency();
30+
}
31+
throw new HibernateException( "Illegal property index: " + property );
32+
}
33+
34+
@Override
35+
public MonetaryAmount instantiate(Supplier<Object[]> valueSupplier, SessionFactoryImplementor sessionFactory) {
36+
final Object[] values = valueSupplier.get();
37+
return new MonetaryAmount( (BigDecimal) values[0], (Currency) values[1] );
38+
}
39+
40+
@Override
41+
public Class<?> embeddable() {
42+
return MonetaryAmountEmbeddable.class;
43+
}
44+
45+
@Override
46+
public Class<MonetaryAmount> returnedClass() {
47+
return MonetaryAmount.class;
48+
}
49+
50+
@Override
51+
public boolean isMutable() {
52+
return true;
53+
}
54+
55+
@Override
56+
public Object deepCopy(Object value) {
57+
MonetaryAmount ma = (MonetaryAmount) value;
58+
return new MonetaryAmount( ma.getAmount(), ma.getCurrency() );
59+
}
60+
61+
@Override
62+
public boolean equals(Object x, Object y) {
63+
if ( x == y ) {
64+
return true;
65+
}
66+
if ( x == null || y == null ) {
67+
return false;
68+
}
69+
return x.equals( y );
70+
}
71+
72+
@Override
73+
public Serializable disassemble(Object value) throws HibernateException {
74+
return (Serializable) deepCopy( value );
75+
}
76+
77+
@Override
78+
public Object assemble(Serializable cached, Object owner) throws HibernateException {
79+
return deepCopy( cached );
80+
}
81+
82+
@Override
83+
public Object replace(Object original, Object target, Object owner) throws HibernateException {
84+
return deepCopy( original ); //TODO: improve
85+
}
86+
87+
@Override
88+
public int hashCode(Object x) throws HibernateException {
89+
return x.hashCode();
90+
}
91+
92+
public static class MonetaryAmountEmbeddable {
93+
private BigDecimal amount;
94+
private Currency currency;
95+
}
96+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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.annotations;
8+
9+
import java.lang.annotation.Retention;
10+
11+
import org.hibernate.usertype.CompositeUserType;
12+
13+
import static java.lang.annotation.ElementType.FIELD;
14+
import static java.lang.annotation.ElementType.METHOD;
15+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
16+
17+
/**
18+
* Form of {@link CompositeType} for describing the id of an id-bag mapping
19+
*
20+
* @since 6.0
21+
*/
22+
@java.lang.annotation.Target({METHOD, FIELD})
23+
@Retention(RUNTIME)
24+
public @interface CollectionIdCompositeType {
25+
26+
/**
27+
* The custom type implementor class
28+
*
29+
* @see CompositeType#value
30+
*/
31+
Class<? extends CompositeUserType<?>> value();
32+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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.annotations;
8+
9+
import java.lang.annotation.Retention;
10+
11+
import org.hibernate.usertype.CompositeUserType;
12+
13+
import static java.lang.annotation.ElementType.FIELD;
14+
import static java.lang.annotation.ElementType.METHOD;
15+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
16+
17+
/**
18+
* Applies a custom {@link CompositeUserType} for the attribute mapping.
19+
*/
20+
@java.lang.annotation.Target({METHOD, FIELD})
21+
@Retention(RUNTIME)
22+
public @interface CompositeType {
23+
24+
/**
25+
* The custom type implementor class
26+
*/
27+
Class<? extends CompositeUserType<?>> value();
28+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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.annotations;
8+
9+
import java.lang.annotation.Repeatable;
10+
import java.lang.annotation.Retention;
11+
import java.lang.annotation.Target;
12+
13+
import org.hibernate.usertype.CompositeUserType;
14+
15+
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
16+
import static java.lang.annotation.ElementType.PACKAGE;
17+
import static java.lang.annotation.ElementType.TYPE;
18+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
19+
20+
/**
21+
* Registers a custom composite user type implementation to be used
22+
* for all references to a particular {@link jakarta.persistence.Embeddable}.
23+
* <p/>
24+
* May be overridden for a specific embedded using {@link org.hibernate.annotations.CompositeType}
25+
*/
26+
@Target( {TYPE, ANNOTATION_TYPE, PACKAGE} )
27+
@Retention( RUNTIME )
28+
@Repeatable( CompositeTypeRegistrations.class )
29+
public @interface CompositeTypeRegistration {
30+
Class<?> embeddableClass();
31+
Class<? extends CompositeUserType<?>> userType();
32+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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.annotations;
8+
9+
import java.lang.annotation.Retention;
10+
import java.lang.annotation.Target;
11+
12+
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
13+
import static java.lang.annotation.ElementType.PACKAGE;
14+
import static java.lang.annotation.ElementType.TYPE;
15+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
16+
17+
/**
18+
* Grouping of {@link CompositeTypeRegistration}
19+
*
20+
* @author Steve Ebersole
21+
*/
22+
@Target( {TYPE, ANNOTATION_TYPE, PACKAGE} )
23+
@Retention( RUNTIME )
24+
public @interface CompositeTypeRegistrations {
25+
CompositeTypeRegistration[] value();
26+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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.annotations;
8+
9+
import org.hibernate.usertype.CompositeUserType;
10+
11+
/**
12+
* Form of {@link CompositeType} for use with map-keys
13+
*
14+
* @since 6.0
15+
*/
16+
public @interface MapKeyCustomCompositeType {
17+
/**
18+
* The custom type implementor class
19+
*
20+
* @see CompositeType#value
21+
*/
22+
Class<? extends CompositeUserType<?>> value();
23+
}

0 commit comments

Comments
 (0)