JAVA-20163 Update example for UserType/CompositeUserType (#14143)
Co-authored-by: timis1 <noreplay@yahoo.com>
This commit is contained in:
parent
70acdb27ee
commit
bb4c9bd411
|
@ -10,6 +10,16 @@ public class Address {
|
||||||
private String country;
|
private String country;
|
||||||
private int zipCode;
|
private int zipCode;
|
||||||
|
|
||||||
|
public Address(String addressLine1, String addressLine2, String city, String country, int zipCode) {
|
||||||
|
this.addressLine1 = addressLine1;
|
||||||
|
this.addressLine2 = addressLine2;
|
||||||
|
this.city = city;
|
||||||
|
this.country = country;
|
||||||
|
this.zipCode = zipCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Address() {}
|
||||||
|
|
||||||
public String getAddressLine1() {
|
public String getAddressLine1() {
|
||||||
return addressLine1;
|
return addressLine1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,19 +2,13 @@ package com.baeldung.hibernate.customtypes;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
|
||||||
import org.hibernate.metamodel.spi.ValueAccess;
|
import org.hibernate.metamodel.spi.ValueAccess;
|
||||||
import org.hibernate.usertype.CompositeUserType;
|
import org.hibernate.usertype.CompositeUserType;
|
||||||
import org.hibernate.usertype.UserType;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Types;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class AddressType implements CompositeUserType<Address>, UserType<Address> {
|
public class AddressType implements CompositeUserType<Address> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object getPropertyValue(Address component, int property) throws HibernateException {
|
public Object getPropertyValue(Address component, int property) throws HibernateException {
|
||||||
|
@ -39,7 +33,8 @@ public class AddressType implements CompositeUserType<Address>, UserType<Address
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address instantiate(ValueAccess values, SessionFactoryImplementor sessionFactory) {
|
public Address instantiate(ValueAccess values, SessionFactoryImplementor sessionFactory) {
|
||||||
return null;
|
return new Address(values.getValue(0, String.class), values.getValue(1,String.class), values.getValue(2, String.class),
|
||||||
|
values.getValue(3, String.class), values.getValue(4,Integer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -47,11 +42,6 @@ public class AddressType implements CompositeUserType<Address>, UserType<Address
|
||||||
return Address.class;
|
return Address.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSqlType() {
|
|
||||||
return Types.VARCHAR;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<Address> returnedClass() {
|
public Class<Address> returnedClass() {
|
||||||
return Address.class;
|
return Address.class;
|
||||||
|
@ -73,36 +63,6 @@ public class AddressType implements CompositeUserType<Address>, UserType<Address
|
||||||
return x.hashCode();
|
return x.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Address nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException {
|
|
||||||
Address empAdd = new Address();
|
|
||||||
empAdd.setAddressLine1(rs.getString(position));
|
|
||||||
|
|
||||||
if (rs.wasNull())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
empAdd.setAddressLine2(rs.getString(position));
|
|
||||||
empAdd.setCity(rs.getString(position));
|
|
||||||
empAdd.setCountry(rs.getString(position));
|
|
||||||
empAdd.setZipCode(rs.getInt(position));
|
|
||||||
|
|
||||||
return empAdd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nullSafeSet(PreparedStatement st, Address value, int index, SharedSessionContractImplementor session) throws SQLException {
|
|
||||||
if (Objects.isNull(value))
|
|
||||||
st.setNull(index, Types.VARCHAR);
|
|
||||||
else {
|
|
||||||
|
|
||||||
st.setString(index, value.getAddressLine1());
|
|
||||||
st.setString(index + 1, value.getAddressLine2());
|
|
||||||
st.setString(index + 2, value.getCity());
|
|
||||||
st.setString(index + 3, value.getCountry());
|
|
||||||
st.setInt(index + 4, value.getZipCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Address deepCopy(Address value) {
|
public Address deepCopy(Address value) {
|
||||||
if (Objects.isNull(value))
|
if (Objects.isNull(value))
|
||||||
|
|
|
@ -34,7 +34,7 @@ public class OfficeEmployee {
|
||||||
@AttributeOverride(name = "cityCode", column = @Column(name = "city_code")),
|
@AttributeOverride(name = "cityCode", column = @Column(name = "city_code")),
|
||||||
@AttributeOverride(name = "number", column = @Column(name = "number"))
|
@AttributeOverride(name = "number", column = @Column(name = "number"))
|
||||||
})
|
})
|
||||||
@Type(value = PhoneNumberType.class)
|
@CompositeType(value = PhoneNumberType.class)
|
||||||
private PhoneNumber employeeNumber;
|
private PhoneNumber employeeNumber;
|
||||||
|
|
||||||
@CompositeType(value = com.baeldung.hibernate.customtypes.AddressType.class)
|
@CompositeType(value = com.baeldung.hibernate.customtypes.AddressType.class)
|
||||||
|
@ -49,10 +49,6 @@ public class OfficeEmployee {
|
||||||
|
|
||||||
@Type(value = com.baeldung.hibernate.customtypes.SalaryType.class,
|
@Type(value = com.baeldung.hibernate.customtypes.SalaryType.class,
|
||||||
parameters = {@Parameter(name = "currency", value = "USD")})
|
parameters = {@Parameter(name = "currency", value = "USD")})
|
||||||
@AttributeOverrides({
|
|
||||||
@AttributeOverride(name = "amount", column = @Column(name = "amount")),
|
|
||||||
@AttributeOverride(name = "currency", column = @Column(name = "currency"))
|
|
||||||
})
|
|
||||||
private Salary salary;
|
private Salary salary;
|
||||||
|
|
||||||
public Salary getSalary() {
|
public Salary getSalary() {
|
||||||
|
|
|
@ -1,20 +1,37 @@
|
||||||
package com.baeldung.hibernate.customtypes;
|
package com.baeldung.hibernate.customtypes;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.usertype.UserType;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.metamodel.spi.ValueAccess;
|
||||||
|
import org.hibernate.usertype.CompositeUserType;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Types;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class PhoneNumberType implements UserType<PhoneNumber> {
|
public class PhoneNumberType implements CompositeUserType<PhoneNumber> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSqlType() {
|
public Object getPropertyValue(PhoneNumber component, int property) throws HibernateException {
|
||||||
return Types.INTEGER;
|
switch (property) {
|
||||||
|
case 0:
|
||||||
|
return component.getCountryCode();
|
||||||
|
case 1:
|
||||||
|
return component.getCityCode();
|
||||||
|
case 2:
|
||||||
|
return component.getNumber();
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(property + " is an invalid property index for class type " + component.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PhoneNumber instantiate(ValueAccess values, SessionFactoryImplementor sessionFactory) {
|
||||||
|
return new PhoneNumber(values.getValue(0, Integer.class), values.getValue(1, Integer.class), values.getValue(2,Integer.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<?> embeddable() {
|
||||||
|
return PhoneNumber.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -37,32 +54,6 @@ public class PhoneNumberType implements UserType<PhoneNumber> {
|
||||||
return x.hashCode();
|
return x.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public PhoneNumber nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException {
|
|
||||||
int countryCode = rs.getInt(position);
|
|
||||||
|
|
||||||
if (rs.wasNull())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
int cityCode = rs.getInt(position);
|
|
||||||
int number = rs.getInt(position);
|
|
||||||
|
|
||||||
return new PhoneNumber(countryCode, cityCode, number);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nullSafeSet(PreparedStatement st, PhoneNumber value, int index, SharedSessionContractImplementor session) throws SQLException {
|
|
||||||
if (Objects.isNull(value)) {
|
|
||||||
st.setNull(index, Types.INTEGER);
|
|
||||||
st.setNull(index+1, Types.INTEGER);
|
|
||||||
st.setNull(index+2, Types.INTEGER);
|
|
||||||
} else {
|
|
||||||
st.setInt(index, value.getCountryCode());
|
|
||||||
st.setInt(index+1, value.getCityCode());
|
|
||||||
st.setInt(index+2, value.getNumber());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PhoneNumber deepCopy(PhoneNumber value) {
|
public PhoneNumber deepCopy(PhoneNumber value) {
|
||||||
if (Objects.isNull(value))
|
if (Objects.isNull(value))
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package com.baeldung.hibernate.customtypes;
|
package com.baeldung.hibernate.customtypes;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class Salary {
|
public class Salary implements Serializable {
|
||||||
|
|
||||||
private Long amount;
|
private Long amount;
|
||||||
private String currency;
|
private String currency;
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
package com.baeldung.hibernate.customtypes;
|
package com.baeldung.hibernate.customtypes;
|
||||||
|
|
||||||
import org.hibernate.HibernateException;
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
import org.hibernate.metamodel.spi.ValueAccess;
|
|
||||||
import org.hibernate.usertype.CompositeUserType;
|
|
||||||
import org.hibernate.usertype.DynamicParameterizedType;
|
import org.hibernate.usertype.DynamicParameterizedType;
|
||||||
import org.hibernate.usertype.UserType;
|
import org.hibernate.usertype.UserType;
|
||||||
|
|
||||||
|
@ -16,38 +12,13 @@ import java.sql.Types;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
public class SalaryType implements UserType<Salary>, CompositeUserType<Salary>, DynamicParameterizedType {
|
public class SalaryType implements UserType<Salary>, DynamicParameterizedType {
|
||||||
|
|
||||||
private String localCurrency;
|
private String localCurrency;
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getPropertyValue(Salary component, int property) throws HibernateException {
|
|
||||||
|
|
||||||
switch (property) {
|
|
||||||
case 0:
|
|
||||||
return component.getAmount();
|
|
||||||
case 1:
|
|
||||||
return component.getCurrency();
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException(property +
|
|
||||||
" is an invalid property index for class type " +
|
|
||||||
component.getClass().getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Salary instantiate(ValueAccess values, SessionFactoryImplementor sessionFactory) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<?> embeddable() {
|
|
||||||
return Salary.class;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSqlType() {
|
public int getSqlType() {
|
||||||
return Types.BIGINT;
|
return Types.VARCHAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -74,12 +45,12 @@ public class SalaryType implements UserType<Salary>, CompositeUserType<Salary>,
|
||||||
@Override
|
@Override
|
||||||
public Salary nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException {
|
public Salary nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException {
|
||||||
Salary salary = new Salary();
|
Salary salary = new Salary();
|
||||||
salary.setAmount(rs.getLong(position));
|
|
||||||
|
|
||||||
if (rs.wasNull())
|
String salaryValue = rs.getString(position);
|
||||||
return null;
|
|
||||||
|
|
||||||
salary.setCurrency(rs.getString(position));
|
salary.setAmount(Long.parseLong(salaryValue.split(" ")[1]));
|
||||||
|
|
||||||
|
salary.setCurrency(salaryValue.split(" ")[0]);
|
||||||
|
|
||||||
return salary;
|
return salary;
|
||||||
}
|
}
|
||||||
|
@ -87,13 +58,11 @@ public class SalaryType implements UserType<Salary>, CompositeUserType<Salary>,
|
||||||
@Override
|
@Override
|
||||||
public void nullSafeSet(PreparedStatement st, Salary value, int index, SharedSessionContractImplementor session) throws SQLException {
|
public void nullSafeSet(PreparedStatement st, Salary value, int index, SharedSessionContractImplementor session) throws SQLException {
|
||||||
if (Objects.isNull(value))
|
if (Objects.isNull(value))
|
||||||
st.setNull(index, Types.BIGINT);
|
st.setNull(index, Types.VARCHAR);
|
||||||
else {
|
else {
|
||||||
|
Long salaryValue = SalaryCurrencyConvertor.convert(value.getAmount(),
|
||||||
st.setLong(index, SalaryCurrencyConvertor.convert(
|
value.getCurrency(), localCurrency);
|
||||||
value.getAmount(),
|
st.setString(index, value.getCurrency() + " " + salaryValue);
|
||||||
value.getCurrency(), localCurrency));
|
|
||||||
st.setString(index + 1, value.getCurrency());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +86,7 @@ public class SalaryType implements UserType<Salary>, CompositeUserType<Salary>,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Serializable disassemble(Salary value) {
|
public Serializable disassemble(Salary value) {
|
||||||
return (Serializable) deepCopy(value);
|
return deepCopy(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -11,10 +11,12 @@ import org.junit.Test;
|
||||||
import jakarta.persistence.TypedQuery;
|
import jakarta.persistence.TypedQuery;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class HibernateCustomTypesIntegrationTest {
|
public class HibernateCustomTypesIntegrationTest {
|
||||||
|
@ -74,12 +76,18 @@ public class HibernateCustomTypesIntegrationTest {
|
||||||
|
|
||||||
doInHibernate(this::sessionFactory, session -> {
|
doInHibernate(this::sessionFactory, session -> {
|
||||||
session.save(e);
|
session.save(e);
|
||||||
|
session.flush();
|
||||||
|
session.refresh(e);
|
||||||
|
|
||||||
TypedQuery<OfficeEmployee> query = session.createQuery("FROM OfficeEmployee OE WHERE OE.empAddress.zipCode = :pinCode", OfficeEmployee.class);
|
TypedQuery<OfficeEmployee> query = session.createQuery("FROM OfficeEmployee OE WHERE OE.empAddress.zipCode = :pinCode", OfficeEmployee.class);
|
||||||
query.setParameter("pinCode",100);
|
query.setParameter("pinCode",100);
|
||||||
int size = query.getResultList().size();
|
final List<OfficeEmployee> resultList = query.getResultList();
|
||||||
|
int size = resultList.size();
|
||||||
|
|
||||||
assertEquals(1, size);
|
assertEquals(1, size);
|
||||||
|
assertNotNull(resultList.get(0).getEmployeeNumber());
|
||||||
|
assertNotNull(resultList.get(0).getEmpAddress());
|
||||||
|
assertNotNull(resultList.get(0).getSalary());
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue