Dear board users,
I face a strange problem with my entity class. Let me try to explain what I intend to do:
I have a hierarchical structure of hardware components that I persist in a database using
Code:
@Inheritance(strategy = InheritanceType.JOINED)
For these components there is a concept named 'resourcing' which means that each hardware component may have an owner and children. You do not need to full yunderstand that to understand the problem. For this mapping I have build an entity called
Resource.
Code:
@Entity
// Keep resourceNumber unique for each controller and resourceType
@Table(name = "ResourceMap", uniqueConstraints = { @UniqueConstraint(columnNames = { "resourceType", "resourceNumber", "ownerId" }) })
@Audited
@Indexed
public class Resource extends BaseEntity
{
public static final String PROPERTY_RESOURCE_TYPE = "resourceType";
public static final String PROPERTY_RESOURCE_LOCATION = "resourceLocation";
public static final String PROPERTY_RESOURCE_NUMBER = "resourceNumber";
public static final String PROPERTY_OWNER = "owner";
public static final String PROPERTY_ENTITY_CLASS = "entityClass";
public static final String PROPERTY_ENTITY_ID = "entityId";
public static final String PROPERTY_CONTROLLER = "controller";
public static final String PROPERTY_CHILDREN = "children";
@Column(name = PROPERTY_RESOURCE_TYPE, nullable = false)
@NotNull
@Enumerated(EnumType.ORDINAL)
@Viewable
private ResourceType resourceType;
@Column(name = PROPERTY_RESOURCE_LOCATION, nullable = false)
@NotNull
@Enumerated(EnumType.ORDINAL)
@Viewable
private ResourceLocation resourceLocation = ResourceLocation.CONTROLLER;
@Column(name = PROPERTY_RESOURCE_NUMBER, nullable = false)
@NotNull
@Viewable
private Short resourceNumber = 0;
@JoinColumn(name = "ownerId", nullable = false)
@ManyToOne(fetch = FetchType.LAZY)
@IndexedEmbedded(depth = 1)
@NotNull
private Resource owner;
@Column(name = PROPERTY_ENTITY_CLASS)
// @NotNull
private Class< entityClass;
@Column(name = PROPERTY_ENTITY_ID)
@NotNull
private String entityId;
@JoinColumn(name = "controllerId", nullable = false)
@ManyToOne(fetch = FetchType.LAZY)
@IndexedEmbedded(depth = 1)
@NotNull
private Controller controller;
@OneToMany(fetch = FetchType.LAZY, mappedBy = PROPERTY_OWNER, cascade = CascadeType.ALL, orphanRemoval = true)
private final Set<Resource> children = new HashSet<>();
// getters and setters
}
As you can see I persist the mapped entity's java class and unique id. I can do that as I like and have the correct values in the database e.g.:
Code:
id version entityClass entityId resourceLocation resourceNumber resourceType controllerId ownerId
949ff828-8cbd-4f81-ba88-07a433fa1250 0 foo.bar.className e923f95f-1266-4690-98c2-68cbfbbcb530 0 0 8 e923f95f-1266-4690-98c2-68cbfbbcb530 949ff828-8cbd-4f81-ba88-07a433fa1250
Now the problem is when I try to read this line using hibernate's criteria API I get a strange SQLGrammarException:
Quote:
Conversion failed when converting the nvarchar value 'foo.bar.className' to data type int
The criteria I am building is quite simple:
Code:
Criteria query = getSession().createCriteria(Resource.class);
query.add(Restrictions.eq(Resource.PROPERTY_ENTITY_CLASS, foo.bar.className.class));
query.add(Restrictions.eq(Resource.PROPERTY_ENTITY_ID, "e923f95f-1266-4690-98c2-68cbfbbcb530"));
return (Resource) query.uniqueResult();
The problem seems to be that the class "foo.bar.className" is itself a persisted entity class. So hibernate trys for some reason to determine a discriminator of type int and maps it to the "entityClass" column. The code for that is located at org.hibernate.loader.criteria.CriteriaQueryTranslator.getTypedValue(Criteria, String, Object).
I have tested it with other classes that are themselves no persisted entities and for these it works as expected.
So the actual question is:
How can I prevent that hibernate resolves thios discriminator value?EDIT:I found somethingout myself. When using the restriction as native SQL-restriction it works:
Code:
Criteria query = getSession().createCriteria(Resource.class);
query.add(Restrictions.sqlRestriction("{alias}." + Resource.PROPERTY_ENTITY_CLASS + " = ?", foo.bar.className.class, ClassType.INSTANCE));
// query.add(Restrictions.eq(Resource.PROPERTY_ENTITY_CLASS, foo.bar.className.class));
query.add(Restrictions.eq(Resource.PROPERTY_ENTITY_ID, "e923f95f-1266-4690-98c2-68cbfbbcb530"));
return (Resource) query.uniqueResult();