Ahoj,

        netus(ím, jestli to standard JPA r(es(í ne(jak obecne(, ale pro 
hibernate jsem musel provést následující ve(c. Je to pome(rne( c(astý problém 
r(es(ený v ne(kolika diskusních threadech (link ted( dohromady nedám, protoz(e 
bych ho musel znovu hledat).

        Pr(ikládám zdrojáky mého modelu, kde jsou enumerace pouz(ity a r(es(ení 
pro Hibernate ORM. Du*lez(ité jsou tr(ídy:

        Enum tr(ídy: Gender a SkillLevel

        Helper classy pro Hibernate:
        EnumUserType<E extends Enum<E>>
        GenderUserType extends EnumUserType<Gender>
        SkillLevelUserType extends EnumUserType<SkillLevel>

        které r(íkají Hibernate, jak se má k daným Enum hodnotám chovat pr(i 
persistování a nac(ítání. Vlastní definice v HBM XML je potom napr(. pro 
Goalkeepera, který pouz(ívá Enumy takováto:

<?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.fgf.ot.model.Goalkeeper" table="GOALKEEPERS">
       <id name="id" column="ID" type="java.lang.Long">
           <generator class="native"/>
       </id>
       <property name="firstname"/>
       <property name="surname"/>
       <property name="age" type="java.lang.Integer"/>
       <property name="gender" type="com.fgf.ot.model.GenderUserType"/>
       <property name="catchSkill" type="com.fgf.ot.model.SkillLevelUserType"/>
       <property name="perception" type="com.fgf.ot.model.SkillLevelUserType"/>
   </class>
</hibernate-mapping>

        Taky bych si to pr(edstavoval jednodus(s(í ;)

Novoj

--
--------------------------------------------------------------
Ing. Jan Novotný
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
http://blog.novoj.net
Mys(lenky dne otce Fura
--------------------------------------------------------------


Tomas Hubalek napsal(a):

Zdar,

mam takovy dotaz. Chtel bych udelat JPA mapping (Hibernate, ale to snad neni podstatne) nasledujicich trid a nevim, jak to oannotovat.

public enum Group { A, B, C}

@Entity

public class Person {

   ...

  @?????

  Set<Group> groups;

   ...

}

Pokud chci jenom jednu property, tak jde pouzit @Enumerated(), ale pro Set to nefunguje.

Mate nekdo nejaky tip? Nebo mam obetovat enum a udelat si UserType.

Tom

!DSPAM:144,45c1d9e5253311903020241!

/*
 * TeamMember.java
 *
 * Created on 14. listopad 2006, 21:39
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

import com.fgf.ot.exception.ValidateException;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;

import java.io.Serializable;


/**
 * Ancestor for every team member.
 *
 * @author Rodina Novotnych
 */
public abstract class TeamMember implements Serializable, Cloneable {

        /**
         * Serial uid.
         */
        static final long serialVersionUID = 562771986777794141L;

        /**
         * Unique id.
         */
        private Long id;

        /**
         * Firstname.
         */
        private String firstname;

        /**
         * Surname.
         */
        private String surname;

        /**
         * Age.
         */
        private Integer age;

        /**
         * Gender.
         */
        private Gender gender;

        /**
         * Getter.
         *
         * @return
         */
        public Long getId() {

                return id;
        }

        /**
         * Setter.
         *
         * @param id
         */
        public void setId(Long id) {

                this.id = id;
        }

        /**
         * Getter.
         *
         * @return
         */
        public String getFirstname() {

                return firstname;
        }

        /**
         * Setter.
         *
         * @param firstname
         */
        public void setFirstname(String firstname) {

                this.firstname = firstname;
        }

        /**
         * Getter.
         *
         * @return
         */
        public String getSurname() {

                return surname;
        }

        /**
         * Setter.
         *
         * @param surname
         */
        public void setSurname(String surname) {

                this.surname = surname;
        }

        /**
         * Getter.
         *
         * @return
         */
        public Integer getAge() {

                return age;
        }

        /**
         * Setter.
         *
         * @param age
         */
        public void setAge(Integer age) {

                this.age = age;
        }

        /**
         * Getter.
         *
         * @return
         */
        public Gender getGender() {

                return gender;
        }

        /**
         * Setter.
         *
         * @param gender
         */
        public void setGender(Gender gender) {

                this.gender = gender;
        }

        /**
         * Performs work, that member of this type should do.
         *
         * @return simple string representing object`s activity
         */
        public abstract String work();

        /**
         * Validates objects itself whether it has initialized all mandatory 
fields, and that fields contains valid
         * values.
         *
         * @throws ValidateException when any error has been found
         */
        public void validate() throws ValidateException {

                if (id == null) {

                        throw new ValidateException("Id cannot be null!");
                }

                if ((age == null) || (age.intValue() <= 0)) {

                        throw new ValidateException("Age cannot be lower than 
1!");
                }

                if (gender == null) {

                        throw new ValidateException("Gender cannot be null!");
                }

                if (firstname == null) {

                        throw new ValidateException("First name cannot be 
null!");
                }

                if (surname == null) {

                        throw new ValidateException("Surname cannot be null!");
                }
        }

        /**
         * Makes copy of current object.
         *
         * @return copy
         *
         * @throws CloneNotSupportedException
         */
        public Object clone() throws CloneNotSupportedException {

                Object retValue;

                retValue = super.clone();

                TeamMember tm = (TeamMember)retValue;

                tm.setId(null);
                tm.setFirstname(firstname);
                tm.setSurname(surname);
                tm.setAge(age);
                tm.setGender(gender);

                return retValue;
        }

        /**
         * HashCode .
         *
         * @return
         */
        public int hashCode() {

                return new 
HashCodeBuilder().append(id).append(firstname).append(surname).append(age).append(gender).hashCode();
        }

        /**
         * True if object is equal to this object.
         *
         * @param obj
         *
         * @return
         */
        public boolean equals(Object obj) {

                if (obj instanceof TeamMember == false) {

                        return false;
                }

                if (this == obj) {

                        return true;
                }

                TeamMember rhs = (TeamMember)obj;

                return new EqualsBuilder().append(id, rhs.id).append(firstname, 
rhs.firstname).append(surname, rhs.surname)
                                                                  .append(age, 
rhs.age).append(gender, rhs.gender).isEquals();
        }

        /**
         * String representation of object.
         *
         * @return
         */
        public String toString() {

                return new 
ToStringBuilder(this).append(id).append(firstname).append(surname).append(age).append(gender)
                                                                                
.toString();
        }
}

/*
 * Sportsman.java
 *
 * Created on 14. listopad 2006, 21:52
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

/**
 * Poor sport worker.
 *
 * @author Rodina Novotnych
 */
public abstract class Sportsman extends TeamMember {

        /**
         * Serial UID.
         */
        static final long serialVersionUID = 2305583800299205422L;

        /**
         * Performs work, that member of this type should do.
         *
         * @return simple string representing object`s activity
         */
        public String work() {

                return "Sportsman tries to make his best in competitions.";
        }
}

/*
 * SkillLevelUserType.java
 *
 * Created on 17. listopad 2006, 22:02
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

/**
 * User type declaration for Hibernate.
 *
 * @author Rodina Novotnych
 */
public class SkillLevelUserType extends EnumUserType<SkillLevel> {

        /**
         * Constructor.
         */
        public SkillLevelUserType() {
                super(SkillLevel.class);
        }
}

/*
 * SkillLevel.java
 *
 * Created on 17. listopad 2006, 22:07
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

/**
 * Represents skill level in various men abilities. 
 **/
public enum SkillLevel {
        LOW,
        AVERAGE,
        INTERMEDIATE,
        HIGH,
        SUPREME;
}
;

/*
 * ServiceMan.java
 *
 * Created on 14. listopad 2006, 21:52
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

/**
 * ServiceMan.
 *
 * @author Rodina Novotnych
 */
public class ServiceMan extends TeamMember {

        /**
         * Serial UID.
         */
        static final long serialVersionUID = 6808040193229777785L;

        /**
         * Performs work, that member of this type should do.
         *
         * @return simple string representing object`s activity
         */
        public String work() {

                return "Service man " + getFirstname() + " " + getSurname() + " 
keeps an eye on things.";
        }
}

/*
 * GoalKeeper.java
 *
 * Created on 14. listopad 2006, 22:21
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;


/**
 * GoalKeeper.
 *
 * @author Rodina Novotnych
 */
public class Goalkeeper extends Sportsman {

        /**
         * Serial UID.
         */
        static final long serialVersionUID = 2984813986540511772L;

        /**
         * Represens ability to block shots on gate.
         */
        private SkillLevel catchSkill;

        /**
         * Represents ability to react quickly.
         */
        private SkillLevel perception;

        /**
         * Getter.
         *
         * @return 
         */
        public SkillLevel getCatchSkill() {

                return catchSkill;
        }

        /**
         * Setter.
         *
         * @param catchSkill 
         */
        public void setCatchSkill(SkillLevel catchSkill) {

                this.catchSkill = catchSkill;
        }

        /**
         * Getter.
         *
         * @return 
         */
        public SkillLevel getPerception() {

                return perception;
        }

        /**
         * Setter.
         *
         * @param perception 
         */
        public void setPerception(SkillLevel perception) {

                this.perception = perception;
        }

        /**
         * Performs work, that member of this type should do.
         *
         * @return simple string representing object`s activity
         */
        public String work() {

                return super.work() + "Goalkeeper " + getFirstname() + " " + 
getSurname() + " with " + perception
                           + " perception and " + catchSkill + " catch skill 
blocks shots on his gate.";
        }

        /**
         * Makes copy of current object.
         *
         * @return copy
         *
         * @throws CloneNotSupportedException
         */
        public Object clone() throws CloneNotSupportedException {

                Object retValue;

                retValue = super.clone();

                Goalkeeper tm = (Goalkeeper)retValue;

                tm.setCatchSkill(catchSkill);
                tm.setPerception(perception);

                return retValue;
        }

        /**
         * HashCode.
         *
         * @return 
         */
        public int hashCode() {

                return new 
HashCodeBuilder().appendSuper(super.hashCode()).append(catchSkill).append(perception).toHashCode();
        }

        /**
         * True if object is equal to this object.
         *
         * @param obj
         *
         * @return
         */
        public boolean equals(Object obj) {

                if (obj instanceof Goalkeeper == false) {

                        return false;
                }

                if (this == obj) {

                        return true;
                }

                Goalkeeper rhs = (Goalkeeper)obj;

                return new 
EqualsBuilder().appendSuper(super.equals(rhs)).append(catchSkill, 
rhs.catchSkill)
                                                                  
.append(perception, rhs.perception).isEquals();
        }

        /**
         * String representation of object.
         *
         * @return
         */
        public String toString() {

                return new 
ToStringBuilder(this).appendSuper(super.toString()).append(catchSkill).append(perception).toString();
        }
}

/*
 * GenderUserType.java
 *
 * Created on 17. listopad 2006, 22:02
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

/**
 * User type declaration for Hibernate.
 *
 * @author Rodina Novotnych
 */
public class GenderUserType extends EnumUserType<Gender> {

        /**
         * Constructor.
         */
        public GenderUserType() {
                super(Gender.class);
        }
}

/*
 * Gender.java
 *
 * Created on 17. listopad 2006, 22:06
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

public enum Gender {
        MALE,
        FEMALE;
}
;

/*
 * EnumUserType.java
 *
 * Created on 17. listopad 2006, 22:05
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

import org.hibernate.HibernateException;

import org.hibernate.usertype.UserType;

import java.io.Serializable;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;


/**
 * Hibernate user type translator. Allows to persist & load enum types into / 
from storage.
 *
 * @see org.hibernate.usertype.UserType
 * @param <E> enum class to be encapsulated.
 */
public abstract class EnumUserType<E extends Enum<E>> implements UserType {

        /**
         * Enum class to be encapsulated.
         */
        private Class<E> clazz = null;

        /**
         * Constructor.
         *
         * @param c 
         */
        protected EnumUserType(Class<E> c) {

                this.clazz = c;
        }

        /**
         * Contains information about how to store enum type.
         */
        private static final int[] SQL_TYPES = { Types.VARCHAR };

        /**
         * Returns information about how to store enum type.
         *
         * @return 
         */
        public int[] sqlTypes() {

                return SQL_TYPES;
        }

        /**
         * Returns class to be returned in connection with stored value.
         *
         * @return 
         */
        public Class returnedClass() {

                return clazz;
        }

        /**
         * Returns value from result set.
         *
         * @param resultSet 
         * @param names 
         * @param owner 
         *
         * @return 
         *
         * @throws HibernateException 
         * @throws SQLException 
         */
        public Object nullSafeGet(ResultSet resultSet, String[] names, Object 
owner)
                                           throws HibernateException, 
SQLException {

                String name = resultSet.getString(names[0]);
                E result = null;

                if (!resultSet.wasNull()) {

                        result = Enum.valueOf(clazz, name);
                }

                return result;
        }

        /**
         * Returns value from prepared statement.
         *
         * @param preparedStatement 
         * @param value 
         * @param index 
         *
         * @throws HibernateException 
         * @throws SQLException 
         */
        public void nullSafeSet(PreparedStatement preparedStatement, Object 
value, int index)
                                         throws HibernateException, 
SQLException {

                if (null == value) {

                        preparedStatement.setNull(index, Types.VARCHAR);
                } else {

                        preparedStatement.setString(index, 
((Enum)value).name());
                }
        }

        /**
         * Deep copies value on input.
         *
         * @param value 
         *
         * @return 
         *
         * @throws HibernateException 
         */
        public Object deepCopy(Object value) throws HibernateException {

                return value;
        }

        /**
         * Returns mutability flag.
         *
         * @return 
         */
        public boolean isMutable() {

                return false;
        }

        /**
         * Converts seralizable into object.
         *
         * @param cached 
         * @param owner 
         *
         * @return 
         *
         * @throws HibernateException 
         */
        public Object assemble(Serializable cached, Object owner)
                                        throws HibernateException {

                return cached;
        }

        /**
         * Converts object into serializable.
         *
         * @param value 
         *
         * @return 
         *
         * @throws HibernateException 
         */
        public Serializable disassemble(Object value)
                                                         throws 
HibernateException {

                return (Serializable)value;
        }

        /**
         * Replaces one object with another.
         *
         * @param original 
         * @param target 
         * @param owner 
         *
         * @return 
         *
         * @throws HibernateException 
         */
        public Object replace(Object original, Object target, Object owner)
                                   throws HibernateException {

                return original;
        }

        /**
         * HashCode.
         *
         * @param x 
         *
         * @return 
         *
         * @throws HibernateException 
         */
        public int hashCode(Object x) throws HibernateException {

                return x.hashCode();
        }

        /**
         * Equals.
         *
         * @param x 
         * @param y 
         *
         * @return 
         *
         * @throws HibernateException 
         */
        public boolean equals(Object x, Object y) throws HibernateException {

                if (x == y) {

                        return true;
                }

                if ((null == x) || (null == y)) {

                        return false;
                }

                return x.equals(y);
        }
}

/*
 * Defender.java
 *
 * Created on 14. listopad 2006, 22:21
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;


/**
 * Defender.
 *
 * @author Rodina Novotnych
 */
public class Defender extends Sportsman {

        /**
         * Serial UID.
         */
        static final long serialVersionUID = 7335172232309760390L;

        /**
         * Represents ability to protect the gate.
         */
        private SkillLevel defendSkill;

        /**
         * Represents speed of the member. The faster member is, the more 
success he has when defending the gate.
         */
        private SkillLevel speed;

        /**
         * Getter.
         *
         * @return 
         */
        public SkillLevel getDefendSkill() {

                return defendSkill;
        }

        /**
         * Setter.
         *
         * @param defendSkill 
         */
        public void setDefendSkill(SkillLevel defendSkill) {

                this.defendSkill = defendSkill;
        }

        /**
         * Getter.
         *
         * @return 
         */
        public SkillLevel getSpeed() {

                return speed;
        }

        /**
         * Setter.
         *
         * @param speed 
         */
        public void setSpeed(SkillLevel speed) {

                this.speed = speed;
        }

        /**
         * Performs work, that member of this type should do.
         *
         * @return simple string representing object`s activity
         */
        public String work() {

                return super.work() + "Defender " + getFirstname() + " " + 
getSurname() + " with " + speed + " speed and "
                           + defendSkill + " defend skill blocks oponent`s 
attacks.";
        }

        /**
         * Makes copy of current object.
         *
         * @return copy
         *
         * @throws CloneNotSupportedException
         */
        public Object clone() throws CloneNotSupportedException {

                Object retValue;

                retValue = super.clone();

                Defender tm = (Defender)retValue;

                tm.setDefendSkill(defendSkill);
                tm.setSpeed(speed);

                return retValue;
        }

        /**
         * HashCode.
         *
         * @return 
         */
        public int hashCode() {

                return new 
HashCodeBuilder().appendSuper(super.hashCode()).append(defendSkill).append(speed).toHashCode();
        }

        /**
         * True if object is equal to this object.
         *
         * @param obj
         *
         * @return
         */
        public boolean equals(Object obj) {

                if (obj instanceof Defender == false) {

                        return false;
                }

                if (this == obj) {

                        return true;
                }

                Defender rhs = (Defender)obj;

                return new 
EqualsBuilder().appendSuper(super.equals(rhs)).append(defendSkill, 
rhs.defendSkill)
                                                                  
.append(speed, rhs.speed).isEquals();
        }

        /**
         * String representation of object.
         *
         * @return
         */
        public String toString() {

                return new 
ToStringBuilder(this).appendSuper(super.toString()).append(defendSkill).append(speed).toString();
        }
}

/*
 * Coach.java
 *
 * Created on 14. listopad 2006, 21:52
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

/**
 * Leader and trainer of sportsmen.
 *
 * @author Rodina Novotnych
 */
public class Coach extends TeamMember {

        /**
         * Serial UID.
         */
        static final long serialVersionUID = 1942739182786754410L;

        /**
         * Performs work, that member of this type should do.
         *
         * @return simple string representing object`s activity
         */
        public String work() {

                return "Coach " + getFirstname() + " " + getSurname() + " 
trains his team.";
        }
}

/*
 * Attacker.java
 *
 * Created on 14. listopad 2006, 22:21
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.fgf.ot.model;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;


/**
 * Attacker.
 *
 * @author Rodina Novotnych
 */
public class Attacker extends Sportsman {

        /**
         * Serial UID.
         */
        static final long serialVersionUID = -7740943376702138147L;

        /**
         * Represents ability to score on oponent`s gate.
         */
        private SkillLevel attackSkill;

        /**
         * Represents speed of the member. The faster member is, the more 
success he has when attacking the gate.
         */
        private SkillLevel speed;

        /**
         * Getter.
         *
         * @return
         */
        public SkillLevel getAttackSkill() {

                return attackSkill;
        }

        /**
         * Setter.
         *
         * @param attackSkill
         */
        public void setAttackSkill(SkillLevel attackSkill) {

                this.attackSkill = attackSkill;
        }

        /**
         * Getter.
         *
         * @return
         */
        public SkillLevel getSpeed() {

                return speed;
        }

        /**
         * Setter.
         *
         * @param speed
         */
        public void setSpeed(SkillLevel speed) {

                this.speed = speed;
        }

        /**
         * Performs work, that member of this type should do.
         *
         * @return simple string representing object`s activity
         */
        public String work() {

                return super.work() + " Attacker " + getFirstname() + " " + 
getSurname() + " with " + speed + " speed and "
                           + attackSkill + " attack skill tries to score on 
oponent`s gate.";
        }

        /**
         * Makes copy of current object.
         *
         * @return copy
         *
         * @throws CloneNotSupportedException
         */
        public Object clone() throws CloneNotSupportedException {

                Object retValue;

                retValue = super.clone();

                Attacker tm = (Attacker)retValue;

                tm.setAttackSkill(attackSkill);
                tm.setSpeed(speed);

                return retValue;
        }

        /**
         * HashCode.
         *
         * @return
         */
        public int hashCode() {

                return new 
HashCodeBuilder().appendSuper(super.hashCode()).append(attackSkill).append(speed).toHashCode();
        }

        /**
         * True if object is equal to this object.
         *
         * @param obj
         *
         * @return
         */
        public boolean equals(Object obj) {

                if (obj instanceof Attacker == false) {

                        return false;
                }

                if (this == obj) {

                        return true;
                }

                Attacker rhs = (Attacker)obj;

                return new 
EqualsBuilder().appendSuper(super.equals(rhs)).append(attackSkill, 
rhs.attackSkill)
                                                                  
.append(speed, rhs.speed).isEquals();
        }

        /**
         * String representation of object.
         *
         * @return
         */
        public String toString() {

                return new 
ToStringBuilder(this).appendSuper(super.toString()).append(attackSkill).append(speed).toString();
        }
}

Odpovedet emailem