5

I wrote a an attribute converter. I want to apply that in an entity. I'm following a purely XML approach so far.

I could not find an equivalent of @Convert in hbm notation.

An example would be appreciated.

When I search for this, understandably, Google returns lots of results about tools/methods on "Auto Converting hbm files to entities vice versa".

Edit: Now I'm suspecting if there is an option in hbm file, given that this is JPA annotation.

The doc of @Convert says:

The Convert annotation is used to specify the conversion of a Basic field or property. It is not necessary to use the Basic annotation or corresponding XML element to specify the basic type.

I'm not entirely sure what it means. Is mixing annotation and XML a way to go in this case?

I've tried this:

public class Person {
   //this is enum
   private Ethnicity ethnicity;
   //.....
}

public enum Ethnicity{
   INDIAN("IND"),
   PERSIAN("PER")
   //...constructors and value field.

   public String value(){
     return this.value;
   }

   public Ethnicity fromValue(String value){
       //logic for conversion
   }
}

Converter:

@Converter
public class EthnicityConverter implements AttributeConverter<Ethnicity,String> {

        @Override
        public Ethnicity convertToEntityAttribute(String attribute) {
            if ( attribute == null ) {
                return null;
            }

            return Ethnicity.fromValue( attribute );
        }

        @Override
        public String convertToDatabaseColumn(Ethnicity dbData) {
            if ( dbData == null ) {
                return null;
            }

            return dbData.value();
        }
}

HBM File:

//....other columns
 <property name="ethnicity">
            <column name="ethnicity"/>
            <type name="EthnicityConverter"/>
        </property>
//....other columns

Edit: Corrected the converter code.

pinkpanther
  • 4,770
  • 2
  • 38
  • 62
  • JPA does not use hibernate config files. It uses `orm.xml`. If you aren't using JPA then kindly remove the JPA tag – Neil Stockton Aug 02 '16 at 12:29
  • @NeilStockton I'm using hibernate, I believe hibernate is also an implementation of JPA, and Convert is from javax.persistence. Am I right? If still there is something wrong, I will remove. thanks. We have equivalent for EnumType.ORDINAL, STRING in hbm files, hence the question. – pinkpanther Aug 02 '16 at 12:33
  • Yes Hibernate does implement JPA, but JPA does NOT use "hbm" files. JPA uses orm.xml. If instead you are using hbm files then you are using HIBERNATE only. – Neil Stockton Aug 02 '16 at 12:38
  • I removed, thought there is javax.persistence.Convert, in case this is popping up on feed of people who follow JPA. There is an element of JPA involved some people might know the answer. It's overlapping. – pinkpanther Aug 02 '16 at 12:41
  • 1
    In case its of use the orm.xml definition of "convert" is on this link http://www.datanucleus.org/products/accessplatform_5_0/jpa/metadata_xml.html#convert – Neil Stockton Aug 02 '16 at 12:46
  • @pinkpanther do you want to persist the string value of enum or the actual enum as type in DB? – Saravana Aug 03 '16 at 04:08
  • @Saravana I want to store string value of enum, for INDIAN("IND"), I want it to store IND in db. – pinkpanther Aug 03 '16 at 07:20
  • @pinkpanther but your doing it in reverse, in the converter class you are trying to persist the enum into DB instead of String value, see my updated converter class. – Saravana Aug 03 '16 at 07:35

3 Answers3

6

The answer from Sarvana is close - you do in fact use the type XML attribute. However, type is used to name a Hibernate Type. However there is a convention to name, instead, an AttributeConverter - simply apply the prefix converted:: to your AttributeConverter FQN. E.g.,

 <property name="ethnicity">
            <column name="ethnicity"/>
            <type name="converted::EthnicityConverter"/>
 </property>

The other option is to auto-apply the converter:

@Converter( autoApply=true)
public class EthnicityConverter implements AttributeConverter<Ethnicity,String> {
    ...
}

Given the converter above, so long as Hibernate knows about it, Hibernate will apply that to any attribute of type Ethnicity.

HTH

Saravana
  • 12,647
  • 2
  • 39
  • 57
Steve Ebersole
  • 9,339
  • 2
  • 48
  • 46
  • I had already autoapply=true in converter, but hibernate was not using it. Using first option mentioned in this solution worked - > prefix converted:: Tested on November 2018. It is weird autoapply=true did not worked for me when changed from jpa-xml to hibernate-xml – Jhovanni Nov 04 '18 at 17:50
  • That tells me you did not tell Hibernate about that converter class – Steve Ebersole Sep 11 '20 at 14:05
2

type is the equivalent xml attribute for Convert annotation.

Below is to convert to Y/N in DB and Boolean in entity.

<property name="status" column="book_status" type="yes_no" not-null="true"/>

Just replace yes_no with your custom converter class

Please see my answer at https://stackoverflow.com/a/37914271/3344829

Official documentation https://docs.jboss.org/hibernate/orm/4.2/manual/en-US/html/ch06.html

Update

<property name="ethnicity" column="ethnicity" type="com.example.EthnicityConverter"/>

Update

@Converter
public class EthnicityConverter implements AttributeConverter<Ethnicity, String> {

    @Override
    public String convertToDatabaseColumn(Ethnicity attribute) {
        // TODO return String value of enum
    }

    @Override
    public Ethnicity convertToEntityAttribute(String dbData) {
        // TODO return resolved enum from string
    }

}
Community
  • 1
  • 1
Saravana
  • 12,647
  • 2
  • 39
  • 57
  • 1
    But entity will still have The enum's actual type? – pinkpanther Aug 02 '16 at 11:52
  • yes, With `Convert` you change type while persisting and retrieving right? so data type will be different in entity and DB – Saravana Aug 02 '16 at 11:57
  • 1
    I'm using an Enum in an entity Person let's say Gender, and there is GenderConverter now we want to map these in Person.hbm.xml? I've tried, but it's giving Could not determine type for GenderConverter error. Note that I've not used any annotation for gender field in Person entity. – pinkpanther Aug 02 '16 at 11:59
  • Could you post the hbm mapping file,converter code in the question and the exception – Saravana Aug 02 '16 at 12:00
  • @pinkpanther i updated the answer, have to mention the fully qualified name in type attribute not just class name – Saravana Aug 02 '16 at 12:46
  • I'm using fully qualified name, in my original code, it's still not working. I've not specified any packages for the classes I mentioned in the example, so I didn't specify in the type of that example. – pinkpanther Aug 02 '16 at 12:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/118908/discussion-between-saravana-and-pinkpanther). – Saravana Aug 02 '16 at 12:51
  • are you getting any exception, if yes could you post the stacktrace? – Saravana Aug 02 '16 at 12:52
  • http://chat.stackoverflow.com/rooms/118908/discussion-between-saravana-and-pinkpanther – pinkpanther Aug 02 '16 at 13:55
  • Thanks, yeah, I gave the incorrect implements Attribute.., dumb me. I changed it now, but still it is giving the same "Could not determine the type for...", I think the problem is we are not supposed to give converter in type attribute, I believe we should give some subtype of UserType or ParameterizedType etc.. as per the link you have provided. Where as the converter is sub-type of AttributeConverter which is not related to hibernate. – pinkpanther Aug 03 '16 at 07:54
  • @pinkpanther not required to have new user type, I have implemented this without user type, it worked. did you modify the same in your POJO, could you post the code you use to persist? – Saravana Aug 03 '16 at 11:05
  • Could you post the complete example with Enum? I'm using org.hibernate.Session#persist. Are you using AttributeConverterTypeAdapter or AttributeConverter? Because the former is hibernate's, while the later is JPA's. This question seems like similar http://stackoverflow.com/questions/22358912/hibernate-envers-fails-with-converter-and-attributeconverter-jpa-2-1 – pinkpanther Aug 03 '16 at 14:29
  • I think you are using hibernate 5, see this https://hibernate.atlassian.net/browse/HHH-9042, I'm using some 4.x.x. Are you using envers? – pinkpanther Aug 03 '16 at 14:38
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/120161/discussion-between-saravana-and-pinkpanther). – Saravana Aug 04 '16 at 18:44
1

I too had to face this issue and i was able to resolve it.

Refer : Hibernate 5 Documentation Example 33. HBM mapping for AttributeConverter

We have to use exact class with package.

Ex :

<property name="ethnicity" column="ethnicity" type="converted::com.example.EthnicityConverter"/>
Chamly Idunil
  • 1,848
  • 1
  • 18
  • 33