Hibernate - how to map an EnumSet - java

I've a Color Enum
public enum color { GREEN, WHITE, RED }
and I have MyEntity that contains it.
public class MyEntity {
private Set<Color> colors;
...
I already have a UserType to map my Enums.
Do you know how to map a Set of Enums in the Hibernate hbm.xml?
Do I need a UserType or there's an easiest way? Thanks
edit: Just to remark, I'm looking for the hbm.xml configuration not the #CollectionOfElements Annotation

I use the solution from the EnumSet mapping thread which relies on the use of <element column>. You just need a table with an id and a string to map the collection (MYENTITY_COLOR here). And the mapping looks like that (the EnumUserType is the one from Java 5 EnumUserType):
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<typedef name="color" class="com.stackoverflow.q2402869.EnumUserType">
<param name="enumClassName">com.stackoverflow.q2402869.Color</param>
</typedef>
<class name="com.stackoverflow.q2402869.MyEntity" entity-name="MyEntity" table="MYENTITY">
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="assigned" />
</id>
<set name="colors" table="MYENTITY_COLORS">
<key column="ID" not-null="true"/>
<element type="color" column="COLOR"/>
</set>
</class>
</hibernate-mapping>
Query might look like this:
select distinct e from MyEntity e join e.colors colors where colors IN ('WHITE', 'GREEN')
The whole solution works well for loads, saves and queries (credits to jasonab).

It seems you need to use the #CollectionOfElements annotation. The doc is at http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-hibspec-collection-extratype, chapter '2.4.6.2.5. Collection of element or composite elements'. The example also maps a Set of Enum.

Related

Hibernate 3.3: how to map list of enums by name

I am working on a project with legacy code and a tight deadline. This application uses Hibernate 3.3.1.GA and XML configurations. It MIGHT be possible to upgrade to a newer version of Hibernate and to integrate JPA to enable the AttributeConverter<Value, Representation> solution I have seen in other questions (like this one), but I really need the path of shortest resistance.
I have an entity that will have a one-to-many relationship with a value that is represented in my Java code as an enum. I have created the table that is supposed to capture the many side as follows:
CREATE TABLE theValueMapping (
id int unsigned NOT NULL AUTO_INCREMENT,
entity int unsigned NOT NULL,
listIndex int unsigned NOT NULL,
value VARCHAR(4) NOT NULL,
PRIMARY KEY (id),
CONSTRAINT FK_theValueMapping_entity FOREIGN KEY (entity) REFERENCES entityTable (id),
UNIQUE UNIQUE_theValueMapping_entity_listIndex_pair (entity, listIndex),
UNIQUE UNIQUE_theValueMapping_entity_value_pair (entity, value)
);
Naturally, my entity has a field that stores a list of the enum instances:
package com.example;
public class TheEntity {
private List<TheValue> theValues;
// everything else dropped, but there are getters and setters
}
And assume the enum is simple:
package com.example;
public enum TheValue {
A,
B,
C;
}
I need to get this mapping to work through XML Hibernate configuration. The best I have been able to devise lets the application launch but fails to load any records:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.example.TheEntity" table="entityTable" lazy="false">
<list name="theValues" table="theValueMapping">
<key column="entity" />
<list-index column="listIndex" />
<element
column="value"
length="4"
type="com.example.TheValue"
not-null="true"
/>
</list>
</class>
</hibernate-mapping>
How can I configure this so Hibernate will load a list of these enum values into my entity from the database?
The answer turned out to be a combination of a typedef approach I had previously rejected plus an inclusion of a missing dependency.
I had not realized that org.hibernate.type.EnumType is defined in the Hibernate Annotations JAR, so I added
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>${hibernate.version}</version>
</dependency>
to my POM.
Then, I reworked my Hibernate configuration to use a typedef to map my enum through this type:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<typedef name="TheValue" class="org.hibernate.type.EnumType">
<param name="enumClass">com.example.TheValue</param>
<param name="type">12</param>
</typedef>
<class name="com.example.TheEntity" table="entityTable" lazy="false">
<list name="theValues" table="theValueMapping">
<key column="entity" />
<list-index column="listIndex" />
<element
column="value"
length="4"
type="TheValue"
not-null="true"
/>
</list>
</class>
</hibernate-mapping>
My thanks to grimarr from the Hibernate forums for showing that I needed hibernate-annotations.jar and to Mike from SO for showing that the typedef approach should work.

Insert Stored Procedure mapped with Hibernate

I'm trying based on some examples and Hibernate documentation for mapping a Stored Procedure, I just need to insert some data wich is not for a single table, but I got the message:
Could not parse mapping document from resource
The mapping file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Data">
<id column="col_id" name="dataId">
<generator class="assigned" />
</id>
<property column="col_liq" name="dataLiq" />
<property column="col_td" name="dataTd" />
<property column="col_numdcto" name="dataNumDoc" />
<sql-insert callable="true" check="none">
{call sp_update_data(?,?,?,?)}
</sql-insert>
</class>
</hibernate-mapping>
The "Data" object is just a POJO.
I will appreciate any idea or sugestion.
just to let others to know how it works due finally I did it.
The mapping is correct with just one point, Hibernate will set the Id as the last field, so the procedure should get it in that position, at least that you do some "trick".
In Java when calling the procedure is like a normal save, the rest is like working with a normal entity.

Hibernate: mapping nested objects -EDITED-

For example, I have the following tables:
USER:
| USERID | USERNAME | USERTYPEID |
USERTYPE:
| USERTYPEID | USERTYPENAME |
So clearly USERTYPEID is a foreign key that a user use to refer to usertype. The JAVA implementation is as such:
I have a class User and a class UserType, where looks like:
public class User {
private int id;
private UserType ut;
....
}
public class UserType {
...
}
In the User.hbm.xml:
<hibernate-mapping>
<class name="com.pretech.User" table="User">
<meta attribute="class-description">
This class contains the employee detail.
</meta>
<id name="id" type="int" column="UserID">
<generator class="native"/>
</id>
</class>
</hibernate-mapping>
So my questions follows:
1) what should I put to map the UserType here and indicate UserType as foreign key?
2) In the case of User includes a list of UserType (may not conceptually true but just want to use as an example), such as:
public class User {
private int id;
private List<UserType> uts;
}
what shoud I do about the hibernate mapping?
EDIT:
Added explanation about foreign key stuff.
There are so many examples available in net for your example, you can also check the hibernate documentation:
For example if you want to have a User entity with a set of UserType's then you can use one-to-many relationship and the mapping file will be:
<class name="User">
<id name="id" column="id">
<generator class="native"/>
</id>
<set name="uts">
<key column="userId"
not-null="true"/>
<one-to-many class="UserType"/>
</set>
</class>
<class name="UserType">
<id name="id" column="id">
<generator class="native"/>
</id>
</class>
And here is another example from the documentation that uses annotations and List instead of Set:
It should be OneToOne or OneToMany depending on UserType is a single reference or multiple (collection list).
Search on Google and you will get numerous tutorials with both xml based and annotations based

Hibernate subclass query : Java.lang.object cannot be cast to, ERROR

I have three Java Class, A which is the parent and B & C are subclasses of A. I have a Hibernate mapping file for A where I have mapped B & C using joined-subclass. Now when I try to query C I get [Ljava.lang.Object; cannot be cast to A. The query that Hibernate generates is correct but why it is not allowing the casting to A?
I have tried the following queries, both result in the same error.
session.createQuery("from Request as req inner join req.category where req.class=Externalrequest and req.requestId=:id");
session.createQuery("from ExternalRequest as ereq inner join ereq.category where ereq.requestId=:id");
Where Request is the parent class and ExternalRequest & InternalRequest are the child class.
And here is the basic structure of my mapping file
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Request" table="request" schema="public">
<id name="requestId" type="integer">
<column name="request_id" />
<generator class="sequence" >
<param name="sequence">request_request_id_seq</param>
</generator>
</id>
<many-to-one name="category" column="category" class="RequestCategory" />
<joined-subclass name="ExternalRequest" table="external_request">
<key column="request_id"/>
.........
</joined-subclass>
<joined-subclass name="InternalRequest" table="internal_request">
<key column="request_id"/>
.......
</joined-subclass>
</class>
[Ljava.lang.Object; is the string representation of an array of Objects.
I think what is happening is that you are trying to assign the result of the query, that is an array of Request or ExternalRequest, to a variable of class Request or ExternalRequest.

hibernate: left outer join with Criteria API, is possible?

I'm new on Hibernate so excuse me for banality but I can't find any answer related to my problem (i tried to search on docs & on SO).
If possible, I would create a left outer join from two tables (t0 and t1) without using HQL; in my case I'd like to use only the Criteria API.
t0 { id, fieldA, fieldB }
t1 { id, fieldC, fieldD }
I don't know which fields will be used for the join, the user can decide it.
I see that the Criteria API has some nice functions such as createAlias or createCriteria but if I use these methods, I can't run a join.
Every table has a class (mapped with a specific hbm.xml) like this:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-access="field">
<class name="it.class.T0" table="t0">
<meta attribute="class-description">Table 0</meta>
<!-- Unique id -->
<id name="id" type="long" column="id">
<generator class="native"/>
</id>
<!-- Natural key -->
<natural-id mutable="true">
<property name="fieldA" type="string" column="fieldA" not-null="true" />
<property name="fieldB" type="string" column="fieldB" not-null="true" />
</natural-id>
<!-- Fields -->
<property name="column1" type="long" column="columnd1" not-null="true" />
<property name="column2" type="string" column="column2" not-null="false" />
</class>
</hibernate-mapping>
The entity class is like this:
public class T0 implements Serializable
{
private static final long serialVersionUID = -8123118569358735984L;
public long id;
public String fieldA;
public String fieldB;
public long column1;
public String column2;
public T0()
{
super();
}
}
Is it possible to create a left outer join programmatically (with the Criteria API) without specifying in the hbm.xml (or in a specific HQL) which fields to use?
No. You can't use a hibernate api to create a join based on a mapping hibernate doesn't know anything about. It kind of defeats the purpose of using hibernate in the first place. Why not just write sql then? ;-)

Categories

Resources