I tried to do it, but it is not working yet. Hibernate maps the column of the custom field as table’s columns.
Maybe I did some mistakes in the mapping.
CustomField
package luminare.model;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Embeddable;
@Embeddable
public class CustomField implements Serializable {
private static final long serialVersionUID = 4044211232164799826L;
private Integer f_int;
private Long f_long;
private Double f_float;
private Date f_date;
private String f_text;
private Boolean f_boolean;
public CustomField() {}
// Copy constructor
public CustomField(CustomField other) {
this.setF_int(other.getF_int());
this.setF_long(other.getF_long());
this.setF_float(other.getF_float());
this.setF_date(other.getF_date());
this.setF_text(other.getF_text());
this.setF_boolean(other.getF_boolean());
}
public CustomField(Integer f_int, Long f_long, Double f_float, Date f_date, String f_text, Boolean f_boolean) {
this.f_int = f_int;
this.f_long = f_long;
this.f_float = f_float;
this.f_date = f_date;
this.f_text = f_text;
this.f_boolean = f_boolean;
}
public Integer getF_int() {
return f_int;
}
public void setF_int(Integer f_int) {
this.f_int = f_int;
}
public Long getF_long() {
return f_long;
}
public void setF_long(Long f_long) {
this.f_long = f_long;
}
public Double getF_float() {
return f_float;
}
public void setF_float(Double f_float) {
this.f_float = f_float;
}
public Date getF_date() {
return f_date;
}
public void setF_date(Date f_date) {
this.f_date = f_date;
}
public String getF_text() {
return f_text;
}
public void setF_text(String f_text) {
this.f_text = f_text;
}
public Boolean getF_boolean() {
return f_boolean;
}
public void setF_boolean(Boolean f_boolean) {
this.f_boolean = f_boolean;
}
}
Composite Type
package luminare.model;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Date;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.BooleanType;
import org.hibernate.type.DateType;
import org.hibernate.type.DoubleType;
import org.hibernate.type.IntegerType;
import org.hibernate.type.LongType;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;
import org.hibernate.usertype.CompositeUserType;
public class FieldValueCompositeType implements CompositeUserType {
private final static Logger logger = LogManager.getLogger(FieldValueCompositeType.class);
public static final FieldValueCompositeType INSTANCE = new FieldValueCompositeType();
@Override
public String[] getPropertyNames() {
return new String[] {
"f_int",
"f_long",
"f_float",
"f_date",
"f_text",
"f_boolean"
};
}
@Override
public Type[] getPropertyTypes() {
return new Type[] {
IntegerType.INSTANCE,
LongType.INSTANCE,
DoubleType.INSTANCE,
DateType.INSTANCE,
StringType.INSTANCE,
BooleanType.INSTANCE
};
}
@Override
public Object getPropertyValue(Object component, int property) throws HibernateException {
logger.debug("property index " + property);
CustomField customField = (CustomField) component;
switch(property) {
case 0:
return customField.getF_int();
case 1:
return customField.getF_long();
case 2:
return customField.getF_float();
case 3:
return customField.getF_date();
case 4:
return customField.getF_text();
case 5:
return customField.getF_boolean();
}
logger.error(property + " is an invalid property index for class type");
throw new IllegalArgumentException(property + " is an invalid property index for class type");
}
@Override
public void setPropertyValue(Object component, int property, Object value) throws HibernateException {
logger.debug("property index " + property);
CustomField customField = (CustomField) component;
switch(property) {
case 0:
customField.setF_int((Integer) value);
case 1:
customField.setF_long((Long) value);
case 2:
customField.setF_float((Double) value);
case 3:
customField.setF_date((Date) value);
case 4:
customField.setF_text((String) value);
case 5:
customField.setF_boolean((Boolean) value);
}
logger.error(property + " is an invalid property index for class type");
throw new IllegalArgumentException(property + " is an invalid property index for class type");
}
@SuppressWarnings("rawtypes")
@Override
public Class returnedClass() {
return CustomField.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return x.equals(y);
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
throws HibernateException, SQLException {
logger.debug("names " + names);
CustomField customField = null;
if(!rs.wasNull()) {
customField = new CustomField();
customField.setF_int(rs.getInt(names[0]));
customField.setF_long(rs.getLong(names[1]));
customField.setF_float(rs.getDouble(names[2]));
customField.setF_date(rs.getDate(names[3]));
customField.setF_text(rs.getString(names[4]));
customField.setF_boolean(rs.getBoolean(names[5]));
}
return customField;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
throws HibernateException, SQLException {
logger.debug("index " + index);
if(value == null) {
st.setNull(index, Types.INTEGER);
st.setNull(index + 1, Types.BIGINT);
st.setNull(index + 2, Types.DOUBLE);
st.setNull(index + 3, Types.DATE);
st.setNull(index + 4, Types.VARCHAR);
st.setNull(index + 5, Types.BOOLEAN);
}
else {
final CustomField customField = (CustomField) value;
st.setInt(index, customField.getF_int());
st.setLong(index + 1, customField.getF_long());
st.setDouble(index + 2, customField.getF_float());
st.setDate(index + 3,java.sql.Date.valueOf(customField.getF_date().toString()));
st.setBoolean(index + 3, customField.getF_boolean());
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
final CustomField receivedParam = (CustomField) value;
final CustomField customField = new CustomField(receivedParam);
return customField;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value, SharedSessionContractImplementor session) throws HibernateException {
return (Serializable) value;
}
@Override
public Object assemble(Serializable cached, SharedSessionContractImplementor session, Object owner)
throws HibernateException {
return cached;
}
@Override
public Object replace(Object original, Object target, SharedSessionContractImplementor session, Object owner)
throws HibernateException {
return this.deepCopy(original);
}
@Override
public int hashCode(final Object value) throws HibernateException {
return value.hashCode();
}
}
Table mapping
package luminare.model;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Table;
import org.hibernate.annotations.TypeDef;
import lt.model.LTTable;
import luminare.database.LUDBConfig;
@Entity(name = "Fields")
@Table(name = "fields", schema = LUDBConfig.LUSchema)
@TypeDef(
name = "fieldvalue",
typeClass = FieldValueCompositeType.class,
defaultForType = CustomField.class
)
public class Fields extends LTTable {
private static final long serialVersionUID = 8439931276045890645L;
@Column(name = "fieldtypeID", nullable = false, updatable = false)
private Integer fieldtypeID;
//@Column(name = "fieldvalue", nullable = false, insertable = true)
@Embedded
private CustomField customfield;
/*
@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(
name="luminaretags", schema = LUDBConfig.LUSchema,
joinColumns=@JoinColumn(name = "tag", insertable = false, updatable = false, nullable = false))
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
private Set<LuminareTags> luminareTags = new HashSet<>(); */
public Integer getFieldtypeID() {
return fieldtypeID;
}
public void setFieldtypeID(Integer fieldtypeID) {
this.fieldtypeID = fieldtypeID;
}
public CustomField getCustomfield() {
return customfield;
}
public void setCustomfield(CustomField customfield) {
this.customfield = customfield;
}
public Fields() {}
}
Error log
[19-12-2018 16:42:10.568] [main 1] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl showHqlAst - --- HQL AST ---
\-[QUERY] Node: 'query'
\-[SELECT_FROM] Node: 'SELECT_FROM'
\-[FROM] Node: 'from'
\-[RANGE] Node: 'RANGE'
\-[DOT] Node: '.'
+-[DOT] Node: '.'
| +-[IDENT] Node: 'luminare'
| \-[IDENT] Node: 'model'
\-[IDENT] Node: 'Fields'
[19-12-2018 16:42:10.589] [main 1] DEBUG org.hibernate.hql.internal.antlr.HqlSqlBaseWalker beforeStatement - select << begin [level=1, statement=select]
[19-12-2018 16:42:10.599] [main 1] DEBUG org.hibernate.hql.internal.ast.tree.FromElement doInitialize - FromClause{level=1} : luminare.model.Fields (<no alias>) -> fields0_
[19-12-2018 16:42:10.602] [main 1] DEBUG org.hibernate.hql.internal.antlr.HqlSqlBaseWalker beforeStatementCompletion - select : finishing up [level=1, statement=select]
[19-12-2018 16:42:10.602] [main 1] DEBUG org.hibernate.hql.internal.ast.HqlSqlWalker processQuery - processQuery() : ( SELECT ( FromClause{level=1} plugin_luminare3.fields fields0_ ) )
[19-12-2018 16:42:10.608] [main 1] DEBUG org.hibernate.hql.internal.ast.HqlSqlWalker createSelectClauseFromFromClause - Derived SELECT clause created.
[19-12-2018 16:42:10.622] [main 1] DEBUG org.hibernate.hql.internal.ast.util.JoinProcessor addJoinNodes - Using FROM fragment [plugin_luminare3.fields fields0_]
[19-12-2018 16:42:10.622] [main 1] DEBUG org.hibernate.hql.internal.antlr.HqlSqlBaseWalker afterStatementCompletion - select >> end [level=1, statement=select]
[19-12-2018 16:42:10.623] [main 1] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl analyze - --- SQL AST ---
\-[SELECT] QueryNode: 'SELECT' querySpaces (plugin_luminare3.fields)
+-[SELECT_CLAUSE] SelectClause: '{derived select clause}'
| +-[SELECT_EXPR] SelectExpressionImpl: 'fields0_.ID as ID1_0_' {FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=plugin_luminare3.fields,tableAlias=fields0_,origin=null,columns={,className=luminare.model.Fields}}}
| \-[SQL_TOKEN] SqlFragment: 'fields0_.insert_date as insert_d2_0_, fields0_.insert_user as insert_u3_0_, fields0_.update_date as update_d4_0_, fields0_.update_user as update_u5_0_, fields0_.f_boolean as f_boolea6_0_, fields0_.f_date as f_date7_0_, fields0_.f_float as f_float8_0_, fields0_.f_int as f_int9_0_, fields0_.f_long as f_long10_0_, fields0_.f_text as f_text11_0_, fields0_.fieldtypeID as fieldty12_0_'
\-[FROM] FromClause: 'from' FromClause{level=1, fromElementCounter=1, fromElements=1, fromElementByClassAlias=[], fromElementByTableAlias=[fields0_], fromElementsByPath=[], collectionJoinFromElementsByPath=[], impliedElements=[]}
\-[FROM_FRAGMENT] FromElement: 'plugin_luminare3.fields fields0_' FromElement{explicit,not a collection join,not a fetch join,fetch non-lazy properties,classAlias=null,role=null,tableName=plugin_luminare3.fields,tableAlias=fields0_,origin=null,columns={,className=luminare.model.Fields}}
[19-12-2018 16:42:10.624] [main 1] DEBUG org.hibernate.hql.internal.ast.ErrorTracker throwQueryException - throwQueryException() : no errors
[19-12-2018 16:42:10.632] [main 1] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl generate - HQL: from luminare.model.Fields
[19-12-2018 16:42:10.632] [main 1] DEBUG org.hibernate.hql.internal.ast.QueryTranslatorImpl generate - SQL: select fields0_.ID as ID1_0_, fields0_.insert_date as insert_d2_0_, fields0_.insert_user as insert_u3_0_, fields0_.update_date as update_d4_0_, fields0_.update_user as update_u5_0_, fields0_.f_boolean as f_boolea6_0_, fields0_.f_date as f_date7_0_, fields0_.f_float as f_float8_0_, fields0_.f_int as f_int9_0_, fields0_.f_long as f_long10_0_, fields0_.f_text as f_text11_0_, fields0_.fieldtypeID as fieldty12_0_ from plugin_luminare3.fields fields0_
[19-12-2018 16:42:10.632] [main 1] DEBUG org.hibernate.hql.internal.ast.ErrorTracker throwQueryException - throwQueryException() : no errors
[19-12-2018 16:42:10.649] [main 1] DEBUG org.hibernate.SQL logStatement -
/*
from
Fields */ select
fields0_.ID as ID1_0_,
fields0_.insert_date as insert_d2_0_,
fields0_.insert_user as insert_u3_0_,
fields0_.update_date as update_d4_0_,
fields0_.update_user as update_u5_0_,
fields0_.f_boolean as f_boolea6_0_,
fields0_.f_date as f_date7_0_,
fields0_.f_float as f_float8_0_,
fields0_.f_int as f_int9_0_,
fields0_.f_long as f_long10_0_,
fields0_.f_text as f_text11_0_,
fields0_.fieldtypeID as fieldty12_0_
from
plugin_luminare3.fields fields0_
Hibernate:
/*
from
Fields */ select
fields0_.ID as ID1_0_,
fields0_.insert_date as insert_d2_0_,
fields0_.insert_user as insert_u3_0_,
fields0_.update_date as update_d4_0_,
fields0_.update_user as update_u5_0_,
fields0_.f_boolean as f_boolea6_0_,
fields0_.f_date as f_date7_0_,
fields0_.f_float as f_float8_0_,
fields0_.f_int as f_int9_0_,
fields0_.f_long as f_long10_0_,
fields0_.f_text as f_text11_0_,
fields0_.fieldtypeID as fieldty12_0_
from
plugin_luminare3.fields fields0_
[19-12-2018 16:42:10.673] [main 1] DEBUG org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions - could not extract ResultSet [n/a]
org.postgresql.util.PSQLException: ERROR: column fields0_.f_boolean does not exist
Position: 201
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2183) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:308) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:143) ~[postgresql-42.2.5.jar:42.2.5]
at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:106) ~[postgresql-42.2.5.jar:42.2.5]
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:60) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.loader.Loader.getResultSet(Loader.java:2167) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1930) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1892) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.loader.Loader.doQuery(Loader.java:937) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:340) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.loader.Loader.doList(Loader.java:2689) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.loader.Loader.doList(Loader.java:2672) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2506) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.loader.Loader.list(Loader.java:2501) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:504) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:395) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:220) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1508) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1537) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1505) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.query.Query.getResultList(Query.java:135) [hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at luminare.MainTest.test(MainTest.java:79) [bin/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_191]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_191]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_191]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_191]
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) [junit-4.12.jar:4.12]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) [junit-4.12.jar:4.12]
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) [junit-4.12.jar:4.12]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) [.cp/:?]
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) [.cp/:?]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:538) [.cp/:?]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:760) [.cp/:?]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:460) [.cp/:?]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:206) [.cp/:?]
[19-12-2018 16:42:10.682] [main 1] WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions - SQL Error: 0, SQLState: 42703
[19-12-2018 16:42:10.683] [main 1] ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions - ERROR: column fields0_.f_boolean does not exist
Position: 201
[19-12-2018 16:42:10.689] [main 1] DEBUG org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl afterTransaction - Initiating JDBC connection release from afterTransaction
[19-12-2018 16:42:10.706] [main 1] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl <init> - On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false