JAVA-20163 Update example for UserType/CompositeUserType (#14143)

Co-authored-by: timis1 <noreplay@yahoo.com>
This commit is contained in:
timis1 2023-06-02 21:12:06 +03:00 committed by GitHub
parent 70acdb27ee
commit bb4c9bd411
7 changed files with 62 additions and 127 deletions

View File

@ -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;
} }

View File

@ -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))

View File

@ -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() {

View File

@ -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))

View File

@ -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;

View File

@ -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

View File

@ -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());
}); });
} }