我正在尝试使用带有 Ebean 的 Play 2.0 重新创建我们的一个 Web 应用程序,但遇到了障碍。我不知道如何将 MySQL 的SET
类型映射到模型中的字段。我已经ENUM
使用注释使列工作,@Enumerated(EnumType.STRING)
但我似乎找不到有关SET
列的任何信息。
该表模仿 crontab:
CREATE TABLE IF NOT EXISTS `schedule` (
`id` int(10) unsigned NOT NULL auto_increment,
`task_id` mediumint(8) unsigned NOT NULL default '0',
`month` set('January','February','March','April','May','June','July','August','September','October','November','December') default NULL,
`mday` set('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','-1','-2','-3','-4','-5','-6','-7','-8','-9','-10') default NULL,
`wday` set('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday') default NULL,
`hour` set('0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23') default NULL,
`minute` set('00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59') default NULL,
`updated` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `event` (`task_id`)
)
我现在按照 MvG 的建议创建了一个 UserType 和相关注释:
@Entity
public class Schedule extends Model {
public enum Month { JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER };
public enum Weekday { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY };
@Id
public Long id;
@ManyToOne(cascade = CascadeType.MERGE)
public Task task;
@Version
public Timestamp updated;
@Type(type="models.EnumSetUserType",parameters=@Parameter(name="enumType",value="models.Schedule$Month"))
@Column(name="month", columnDefinition="SET('JANUARY','FEBRUARY','MARCH','APRIL','MAY','JUNE','JULY','AUGUST','SEPTEMBER','OCTOBER','NOVEMBER','DECEMBER')")
@MonthEnum
public EnumSet<Month> months;
@Type(type="models.IntegerSetUserType")
@IntegerSet(min=-30,max=30)
@Column(name="mday",columnDefinition="SET('1','2','3','4','5','6','7','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','-1','-2','-3','-4','-5','-6','-7','-8','-9')")
public Set<Integer> mdays;
@Type(type="models.EnumSetUserType", parameters = @Parameter(name="enumType", value="models.Schedule$Weekday"))
@Column(name="wday", columnDefinition="SET('MONDAY','TUESDAY','WEDNESDAY','THURSDAY','FRIDAY','SATURDAY')")
@WeekdayEnum
public EnumSet<Weekday> weekdays;
@Type(type="models.IntegerSetUserType")
@IntegerSet(min=0,max=23)
@Column(name="hour",columnDefinition="SET('0','1','2','3','4','5','6','7','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23')")
public Set<Integer> hours;
@Type(type="models.IntegerSetUserType")
@IntegerSet(min=0,max=59)
@Column(name="minute",columnDefinition="SET('00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40','41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59')")
public Set<Integer> minutes;
public static Finder<Long,Schedule> find = new Finder<Long,Schedule>(Long.class, Schedule.class);
}
EnumSetUserType
:
public class EnumSetUserType<E extends Enum<E>> implements UserType, ParameterizedType, Serializable {
private Class<? extends EnumSet> clazz = null;
private Class<E> enum_type = null;
@Override
public void setParameterValues(Properties parameters) {
String enum_class_name = parameters.getProperty("enumType");
try {
enum_type = ReflectHelper.classForName(parameters.getProperty("enumType"), this.getClass()).asSubclass(Enum.class);
//enum_type = (Class<E>) Class.forName(enum_class_name);
//enum_type = (Class<E>) Play.application().classloader().loadClass(enum_class_name);
}
catch (ClassNotFoundException e) {
throw new HibernateException("enum class " + enum_class_name + " not found", e);
}
}
@Override
public Object nullSafeGet(ResultSet rs, String[] column_names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
String value_str = rs.getString(column_names[0]);
System.out.println("getting " + column_names[0] + " using " + getClass());
if (rs.wasNull())
return null;
List<E> enum_values = new ArrayList<E>();
for (String value : value_str.split(","))
enum_values.add(Enum.valueOf(enum_type, value));
return EnumSet.copyOf(enum_values);
}
@Override
public void nullSafeSet(PreparedStatement statement, Object object, int index, SessionImplementor session) throws HibernateException, SQLException {
System.out.println("Setting " + index + " to " + object + " using " + getClass());
if (object == null) {
statement.setNull(index, Types.VARCHAR);
return;
}
Set<E> values = (Set<E>) object;
StringBuilder sb = new StringBuilder();
for (E value : values)
sb.append(value.name()).append(",");
System.out.println("Setting " + index + " to " + sb.length() + " using " + getClass());
statement.setString(index, sb.substring(0, sb.length() - 1));
}
@Override
public int[] sqlTypes() {
return new int[] { Types.VARCHAR };
}
@Override
public Class returnedClass() {
return clazz;
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if (x == y)
return true;
if (x == null || y == null)
return false;
return x.equals(y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
}
它不再报告任何错误,但即使我手动填充并保存Schedule
在控制器操作中,Set
字段也不会保存在数据库中。我怎样才能让 Play+Ebean 与这张桌子一起工作?