英文:
How to perform a query with a converted value
问题
我有一个简单的转换器,用于将DayOfWeek
映射为整数,以匹配使用Calendar星期几值的传统数据代码。然而,在执行条件查询时,似乎是使用了DayOfWeek的序数值,而不是我的转换后的值。
default Optional<ProgramSchedule> findByProgramWeekAndDay(final Program program, int week, final DayOfWeek dayOfWeek) {
return findOne(((root, query, cb) ->
cb.and(
cb.equal(root.get(ProgramSchedule_.program), program),
cb.equal(root.get(ProgramSchedule_.week), week),
cb.equal(root.get(ProgramSchedule_.dayOfWeek), dayOfWeek))
));
}
并使用以下方式调用它:
programSchedules.findByProgramWeekAndDay(psFdProgram, 1, DayOfWeek.TUESDAY)
这给我带来了以下问题,其中参数2应该是星期几,但我期望它是3
,这是Calendar.TUESDAY的星期几值。
ype.descriptor.sql.BasicBinder TRACE binding parameter [1] as [VARCHAR] - [PS-FD]
ype.descriptor.sql.BasicBinder TRACE binding parameter [2] as [INTEGER] - [1]
我正在使用Spring JPA。
转换器如下所示:
@Component
@Converter(autoApply = true)
public class DayOfWeekConverter implements AttributeConverter<DayOfWeek, Integer> {
@Override
public Integer convertToDatabaseColumn(final DayOfWeek dayOfWeek) {
if (dayOfWeek == null) {
return null;
} else if (DayOfWeek.SUNDAY == dayOfWeek) {
return Calendar.SUNDAY;
} else if (DayOfWeek.MONDAY == dayOfWeek) {
return Calendar.MONDAY;
} else if (DayOfWeek.TUESDAY == dayOfWeek) {
return Calendar.TUESDAY;
} else if (DayOfWeek.WEDNESDAY == dayOfWeek) {
return Calendar.WEDNESDAY;
} else if (DayOfWeek.THURSDAY == dayOfWeek) {
return Calendar.THURSDAY;
} else if (DayOfWeek.FRIDAY == dayOfWeek) {
return Calendar.FRIDAY;
} else if (DayOfWeek.SATURDAY == dayOfWeek) {
return Calendar.SATURDAY;
} else {
throw new IllegalStateException();
}
}
@Override
public DayOfWeek convertToEntityAttribute(final Integer dbValue) {
if (dbValue == null) {
return null;
} else if (Calendar.SUNDAY == dbValue) {
return DayOfWeek.SUNDAY;
} else if (Calendar.MONDAY == dbValue) {
return DayOfWeek.MONDAY;
} else if (Calendar.TUESDAY == dbValue) {
return DayOfWeek.TUESDAY;
} else if (Calendar.WEDNESDAY == dbValue) {
return DayOfWeek.WEDNESDAY;
} else if (Calendar.THURSDAY == dbValue) {
return DayOfWeek.THURSDAY;
} else if (Calendar.FRIDAY == dbValue) {
return DayOfWeek.FRIDAY;
} else if (Calendar.SATURDAY == dbValue) {
return DayOfWeek.SATURDAY;
} else {
throw new IllegalArgumentException(String.format("dbValue=%d is not valid", dbValue));
}
}
}
我用以下方式注释了dayOfWeek:
@Id
@Column(name = "Day", nullable = false)
@Convert(converter = DayOfWeekConverter.class) // I had it without this one as well
private DayOfWeek dayOfWeek;
这不仅限于条件查询,它也在JPQL查询中发生:
@Query("from ProgramSchedule p where p.program = :program and week = :week and dayOfWeek = :dayOfWeek")
Optional<ProgramSchedule> findByProgramWeekAndDay(final Program program, int week, final DayOfWeek dayOfWeek);
产生了以下结果:
where
programsch0_.Program=?
and programsch0_.Week=?
and programsch0_.Day=?
ype.descriptor.sql.BasicBinder TRACE binding parameter [1] as [VARCHAR] - [PS-FD]
ype.descriptor.sql.BasicBinder TRACE binding parameter [2] as [INTEGER] - [1]
ype.descriptor.sql.BasicBinder TRACE binding parameter [3] as [INTEGER] - [1]
英文:
I have a simple converter to map DayOfWeek
to an Integer to match the legacy data code which used Calendar day of week values. However, when I am doing criteria queries, it appears to be using the ordinal value of DayOfWeek rather than my converted value.
default Optional<ProgramSchedule> findByProgramWeekAndDay(final Program program, int week, final DayOfWeek dayOfWeek) {
return findOne(((root, query, cb) ->
cb.and(
cb.equal(root.get(ProgramSchedule_.program), program),
cb.equal(root.get(ProgramSchedule_.week), week),
cb.equal(root.get(ProgramSchedule_.dayOfWeek), dayOfWeek))
));
}
And calling it with
programSchedules.findByProgramWeekAndDay(psFdProgram, 1, DayOfWeek.TUESDAY)
Gives me the following where parameter 2 was supposed be the day of the week, however, I was expecting it to be 3
which is the day of week value for Calendar.TUESDAY.
ype.descriptor.sql.BasicBinder TRACE binding parameter [1] as [VARCHAR] - [PS-FD]
ype.descriptor.sql.BasicBinder TRACE binding parameter [2] as [INTEGER] - [1]
I'm using Spring JPA
The converter looks like this
@Component
@Converter(autoApply = true)
public class DayOfWeekConverter implements AttributeConverter<DayOfWeek, Integer> {
@Override
public Integer convertToDatabaseColumn(final DayOfWeek dayOfWeek) {
if (dayOfWeek == null) {
return null;
} else if (DayOfWeek.SUNDAY == dayOfWeek) {
return Calendar.SUNDAY;
} else if (DayOfWeek.MONDAY == dayOfWeek) {
return Calendar.MONDAY;
} else if (DayOfWeek.TUESDAY == dayOfWeek) {
return Calendar.TUESDAY;
} else if (DayOfWeek.WEDNESDAY == dayOfWeek) {
return Calendar.WEDNESDAY;
} else if (DayOfWeek.THURSDAY == dayOfWeek) {
return Calendar.THURSDAY;
} else if (DayOfWeek.FRIDAY == dayOfWeek) {
return Calendar.FRIDAY;
} else if (DayOfWeek.SATURDAY == dayOfWeek) {
return Calendar.SATURDAY;
} else {
throw new IllegalStateException();
}
}
@Override
public DayOfWeek convertToEntityAttribute(final Integer dbValue) {
if (dbValue == null) {
return null;
} else if (Calendar.SUNDAY == dbValue) {
return DayOfWeek.SUNDAY;
} else if (Calendar.MONDAY == dbValue) {
return DayOfWeek.MONDAY;
} else if (Calendar.TUESDAY == dbValue) {
return DayOfWeek.TUESDAY;
} else if (Calendar.WEDNESDAY == dbValue) {
return DayOfWeek.WEDNESDAY;
} else if (Calendar.THURSDAY == dbValue) {
return DayOfWeek.THURSDAY;
} else if (Calendar.FRIDAY == dbValue) {
return DayOfWeek.FRIDAY;
} else if (Calendar.SATURDAY == dbValue) {
return DayOfWeek.SATURDAY;
} else {
throw new IllegalArgumentException(String.format("dbValue=%d is not valid", dbValue));
}
}
}
I annotated dayOfWeek as follows
@Id
@Column(name = "Day", nullable = false)
@Convert(converter = DayOfWeekConverter.class) // I had it without this one as well
private DayOfWeek dayOfWeek;
It's not limited to criteria queries either, it also occurs with JPQL queries:
@Query("from ProgramSchedule p where p.program = :program and week = :week and dayOfWeek = :dayOfWeek")
Optional<ProgramSchedule> findByProgramWeekAndDay(final Program program, int week, final DayOfWeek dayOfWeek);
yields
where
programsch0_.Program=?
and programsch0_.Week=?
and programsch0_.Day=?
ype.descriptor.sql.BasicBinder TRACE binding parameter [1] as [VARCHAR] - [PS-FD]
ype.descriptor.sql.BasicBinder TRACE binding parameter [2] as [INTEGER] - [1]
ype.descriptor.sql.BasicBinder TRACE binding parameter [3] as [INTEGER] - [1]
答案1
得分: 1
@Id
和@Convert
不能同时使用,所以你需要使用@IdClass
,像这样:
@Entity
@IdClass(MyEntity.class)
public class MyId {
@Id
private DayOfWeek dayOfWeek;
...
}
public class MyEntity implements Serializable {
@Column(name = "Day")
@Convert(converter = DayOfWeekConverter.class)
private DayOfWeek dayOfWeek;
}
编辑 根据文档,上面的代码也不起作用,所以我寻找了一种解决方法,找到了这个:
@Entity
public class MyEntity {
@EmbeddedId
private DayOfWeek dayOfWeek;
...
}
@Embeddable
public static class Id {
@Column(name = "Day")
@Convert(converter = DayOfWeekConverter.class)
private DayOfWeek dayOfWeek;
}
英文:
@Id
and @Convert
cannot be used together, so you have to use an @IdClass
, like so:
@Entity
@IdClass(MyEntity.class)
public class MyId {
@Id
private DayOfWeek dayOfWeek;
...
}
public class MyEnity implements Serializable {
@Column(name = "Day")
@Convert(converter = DayOfWeekConverter.class)
private DayOfWeek dayOfWeek;
}
EDIT According to docs the above code also doesn't work, so I looked for a workaround and found this:
@Entity
public class MyEntity {
@EmbeddedId
private DayOfWeek dayOfWeek;
...
}
@Embeddable
public static class Id {
@Column(name = "Day")
@Convert(converter = DayOfWeekConverter.class)
private DayOfWeek dayOfWeek;
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论