Search code examples
usertype

how to create a manytomany relationship between an entity and org.hibernate.usertype.UserType


I have an entity like this:

 @Entity
    @Table(name = "PLATFORM")
    public class Platform{

        @Id
        @Column(name = "PLATFORM_ID")
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Integer platformId;

        @ManyToOne(fetch=FetchType.EAGER)
        @JoinColumn(name="PLATFORM_TYPE_ID")
        private PlatformType platformType;

        //must be manytomany but how?
        private List<MimeType> supportedMimeTypes;
        ...

And I have a MimeType class which is a org.hibernate.usertype.UserType indeed.

import java.sql.Types;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class MimeType extends EnumarationType{
    private static final long serialVersionUID = 1L;

    public static final MimeType XML = new MimeType(new Integer(0), "XML");
    public static final MimeType JSON = new MimeType(new Integer(1), "JSON");

    protected static ArrayList<MimeType> list = new ArrayList<MimeType>();

    static {
        SQL_TYPES = new int[] { Types.INTEGER };
        list.add(XML);
        list.add(JSON);
    }

    public MimeType(){      
    }

    public MimeType(Integer value, String label) {
        super(value, label);
    }

    public List<?> getList() {
        return list;
    }

    public static MimeType getById(int id) {
        Iterator<MimeType> it = list.iterator();
        while (it.hasNext()) {
            MimeType status = it.next();
            int statusId = Integer.parseInt(status.getValue());
            if (statusId == id)
                return status;
        }
        return null;
    }

    public static MimeType getByName(String name) {
        Iterator<MimeType> it = list.iterator();
        while (it.hasNext()) {
            MimeType status = it.next();
            String statusName = status.getLabel();
            if (statusName.equalsIgnoreCase(name))
                return status;
        }
        return null;
    }
}

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Iterator;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;

public abstract class EnumarationTypeBase implements UserType, Serializable {

    protected static int[] SQL_TYPES = { Types.VARCHAR };

    protected String label;

    protected Object value;

    protected String resourceKey;

    public EnumarationTypeBase() {
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public abstract List<?> getList();

    private Object getValue() {
        return value;
    }

    public void setValue(Object value) {
        this.value = value;
    }

    public EnumarationTypeBase resolveFromValue(Object value) {
        List<?> list = getList();

        if (list == null)
            return null;

        EnumarationTypeBase result = null;
        for (Iterator<?> itr = list.iterator(); itr.hasNext();) {
            EnumarationTypeBase enm = (EnumarationTypeBase) itr.next();
            if (enm.getValue().toString().equals(value.toString())) {
                result = enm;
                break;
            }
        }

        return result;
    }

    public EnumarationTypeBase resolveFromLabel(Object label) {
        List<?> list = getList();

        if (list == null)
            return null;

        EnumarationTypeBase result = null;
        for (Iterator<?> itr = list.iterator(); itr.hasNext();) {
            EnumarationTypeBase enm = (EnumarationTypeBase) itr.next();
            if (enm.getLabel().equals(label.toString())) {
                result = enm;
                break;
            }
        }

        return result;
    }

    public String toString() {
        return getLabel();
    }

    public int[] sqlTypes() {
        return SQL_TYPES;
    }

    public Class<?> returnedClass() {
        return getClass();
    }

    public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException,
            SQLException {

        value = resultSet.getString(names[0]);

        return resultSet.wasNull() ? null : resolveFromValue(value);
    }

    public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException,
            SQLException {
        EnumarationTypeBase enumType = (EnumarationTypeBase) value;
        if (value == null) {
            statement.setNull(index, sqlTypes()[0]);
        } else {
            statement.setString(index, enumType.getValue().toString());
        }
    }

    public boolean equals(Object x, Object y) {
        if (x == y)
            return true;
        if (null == x || null == y)
            return false;
        return x.equals(y);
    }

    public boolean equals(Object obj) {
        if (obj instanceof EnumarationTypeBase)
            return this.getValue().equals(((EnumarationTypeBase) obj).getValue());

        return super.equals(obj);
    }

    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }

    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }

    public Object deepCopy(Object value) {
        return value;
    }

    public boolean isMutable() {
        return false;
    }

    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    public int hashCode() {
        return (new Integer(this.getValue().toString())).intValue();
    }

    public String getResourceKey() {
        if (resourceKey == null)
            resourceKey = resolveFromValue(this.value).resourceKey;
        return resourceKey;
    }

    public void setResourceKey(String resourceKey) {
        this.resourceKey = resourceKey;
    }
}

public abstract class EnumarationType extends EnumarationTypeBase {

    protected static int[] SQL_TYPES = { Types.VARCHAR };

    public EnumarationType() {
    }

    public EnumarationType(Integer value, String label) {
        this.value = value.toString();
        this.label = label;
    }

    public EnumarationType(String value, String label) {
        this.value = value.toString();
        this.label = label;
    }

    public EnumarationType(Integer value, String label, String resourceKey) {
        this.value = value.toString();
        this.label = label;
        this.resourceKey = resourceKey;
    }

    public String getValue() {
        return (String) value;
    }

    public BigDecimal getBigDecimalValue() {
        BigDecimal tValue = new BigDecimal(getValue());
        return tValue;
    }

    public void setValue(String value) {
        this.value = value;
    }

}

So how could i define a manytomany relationship between the entity Platform and non-entity usertype MimeType.

Please help.


Solution

  • I solved the problem. Here is the working code

    ...  
    
        @ElementCollection(targetClass = MimeType.class,fetch=FetchType.EAGER) 
        @CollectionTable(name = "PLATFORM_MIME_TYPE", joinColumns = @JoinColumn(name = "PLATFORM_ID"))
        @Enumerated(EnumType.ORDINAL)
        @Column(name = "MIME_TYPE_ID", columnDefinition="integer")
        @Type(
                type = Constants.ENUMERATION_TYPE,
                parameters = {
                        @Parameter(
                            name  = "enumClass",                     
                            value = "com.ba.reme.model.enums.MimeType"),
                        @Parameter(
                            name  = "identifierMethod",
                            value = "toInt"),
                        @Parameter(
                            name  = "valueOfMethod",
                            value = "fromInt")
                        }
            )
        private Set<MimeType> supportedMimeTypes;
    
    
        ...
    

    And the MimeType enum :

    public enum MimeType {
        XML(1), 
        JSON(2),
        RSS(3);
    
        private int value;
    
        MimeType(int value) {
            this.value = value;
        }
    
        // the identifierMethod
        public int toInt() {
          return value;
        }
    
         // the valueOfMethod
         public  static MimeType fromInt(int value) {   
             switch(value) {
                 case 2: return JSON;
                 case 3: return RSS;
                 default: return XML;
             }
        }
    
        public String toString() {
          switch(this) {
            case RSS: return "rss";
            case JSON: return "json";
            default: return "xml";
          }
        }
    
    }