Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA/Hibernate, @Embedded and Enum

I'm trying to persist an Enum as an Embedded value (ideally using it's String representation, but even ordinal would be ok right now)

The Enum:

@Embeddable
public enum DayOfTheWeek {
 SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;

 public int toCalendar() throws EnumConstantNotPresentException{
  switch (this) {
  case SUNDAY:
   return Calendar.SUNDAY;
  case MONDAY:
   return Calendar.MONDAY;
  case TUESDAY:
   return Calendar.TUESDAY;
  case WEDNESDAY:
   return Calendar.WEDNESDAY;
  case THURSDAY:
   return Calendar.THURSDAY;
  case FRIDAY:
   return Calendar.FRIDAY;
  case SATURDAY:
   return Calendar.SATURDAY;
  }
  throw new EnumConstantNotPresentException(this.getClass(), "Unknown value ["+this.name()+"]");
 }

 public static DayOfTheWeek fromCalendarDay(int day) {
  switch (day) {
  case Calendar.SUNDAY:
   return SUNDAY;
  case Calendar.MONDAY:
   return MONDAY;
  case Calendar.TUESDAY:
   return TUESDAY;
  case Calendar.WEDNESDAY:
   return WEDNESDAY;
  case Calendar.THURSDAY:
   return THURSDAY;
  case Calendar.FRIDAY:
   return FRIDAY;
  case Calendar.SATURDAY:
   return SATURDAY;
  }
  return null;
 }

 public static DayOfTheWeek getByDate(Date date) {
  Calendar calendar = GregorianCalendar.getInstance();
  calendar.setTime(date);
  return fromCalendarDay(calendar.get(Calendar.DAY_OF_WEEK));
 }

 @Override
 /**
  * Should return the localized day of the week
  */
 public String toString() {
  Calendar c = new GregorianCalendar();
  c.set(Calendar.DAY_OF_WEEK, this.toCalendar());
  SimpleDateFormat sdf = (SimpleDateFormat) SimpleDateFormat
    .getInstance();
  sdf.applyPattern("EEEEEEEEEE");

  return sdf.format(c.getTime());
 }

}

The Class :

@Entity
public class Day implements Serializable {

 ...

 @Enumerated
 @Embedded
 private DayOfTheWeek dayOfTheWeek;

 ...

 @Id
 @GeneratedValue
 private Long id;

 public void setId(Long id) {
  this.id = id;
 }

 public Long getId() {
  return id;
 }

 public void setDayOfTheWeek(DayOfTheWeek dayOfTheWeek) {
  this.dayOfTheWeek = dayOfTheWeek;
 }

 public DayOfTheWeek getDayOfTheWeek() {
  return dayOfTheWeek;
 }

 ...
}

Now, here is the interesting part of the stack when persisting "Day" :

org.springframework.orm.hibernate3.HibernateSystemException: No default constructor for entity: xxx.yyyy.zzz.DayOfTheWeek; nested exception is org.hibernate.InstantiationException: No default constructor for entity: xxx.yyyy.zzz.DayOfTheWeek

I've tried several things and couldn't get it to work in any way, any idea ?

like image 927
temsa Avatar asked Feb 11 '10 10:02

temsa


People also ask

Which annotation in JPA may be used to specify whether enum should be persisted as number in database column?

The @Enumerated annotation enables you to define how an enum attribute gets persisted in the database. By default, all JPA implementations map the ordinal value of the enum to a numeric database column.

What is the default enum value type in JPA?

We have an entity with an enum field - emailCommunicationStatus , and we want to set a default value for it using JPA annotations - 'UNKNOWN' . However, when we save the entity to the DB, the value of this field is null and not . For the boolean field - isLocked the correct default value ( false ) is saved.

What is ordinal in enum?

ordinal() tells about the ordinal number(it is the position in its enum declaration, where the initial constant is assigned an ordinal of zero) for the particular enum.


2 Answers

Remove the @Embedded and @Embeddable annotations just use the @Enumerated(EnumType.STRING) to get it as a string.

As a side note, consider defining your enum like this to avoid the switch

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public enum DayOfTheWeek {
    SUNDAY {
        @Override
        public int toCalendar() {
            return Calendar.SUNDAY;
        }

    },
    MONDAY {
        @Override
        public int toCalendar() {
            return Calendar.MONDAY;
        }
    },
    TUESDAY {
        @Override
        public int toCalendar() {
            return Calendar.TUESDAY;
        }
    },
    WEDNESDAY {
        @Override
        public int toCalendar() {
            return Calendar.WEDNESDAY;
        }
    },
    THURSDAY {
        @Override
        public int toCalendar() {
            return Calendar.THURSDAY;
        }
    },
    FRIDAY {
        @Override
        public int toCalendar() {
            return Calendar.FRIDAY;
        }
    },
    SATURDAY {
        @Override
        public int toCalendar() {
            return Calendar.SATURDAY;
        }
    };

    public abstract int toCalendar();

    public static DayOfTheWeek fromCalendarDay(int day) {

        for (DayOfTheWeek dayOfWeek : DayOfTheWeek.values()) {
            if (dayOfWeek.toCalendar() == day) {
                return dayOfWeek;
            }
        }

        return null; // Consider throwing IllegalArgumentException
    }

    public static DayOfTheWeek getByDate(Date date) {
        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(date);
        return fromCalendarDay(calendar.get(Calendar.DAY_OF_WEEK));
    }

    @Override
    /*
     * Should return the localized day of the week
     */
    public String toString() {
        Calendar c = new GregorianCalendar();
        c.set(Calendar.DAY_OF_WEEK, this.toCalendar());
        SimpleDateFormat sdf = (SimpleDateFormat) SimpleDateFormat
                .getInstance();
        sdf.applyPattern("EEEEEEEEEE");

        return sdf.format(c.getTime());
    }

}
like image 185
Lombo Avatar answered Oct 05 '22 09:10

Lombo


Why do you want the enum to be @Embeddable. What is wrong with simply annotating it as a column?

@Enumerated(EnumType.STRING)
@Column(name = "...")
public DayOfTheWeek getDayOfTheWeek() {
    return dayOfTheWeek;
}
like image 44
Grzegorz Oledzki Avatar answered Oct 05 '22 09:10

Grzegorz Oledzki