如何使用转换后的值执行查询

huangapple go评论94阅读模式
英文:

How to perform a query with a converted value

问题

我有一个简单的转换器,用于将DayOfWeek映射为整数,以匹配使用Calendar星期几值的传统数据代码。然而,在执行条件查询时,似乎是使用了DayOfWeek的序数值,而不是我的转换后的值。

  1. default Optional<ProgramSchedule> findByProgramWeekAndDay(final Program program, int week, final DayOfWeek dayOfWeek) {
  2. return findOne(((root, query, cb) ->
  3. cb.and(
  4. cb.equal(root.get(ProgramSchedule_.program), program),
  5. cb.equal(root.get(ProgramSchedule_.week), week),
  6. cb.equal(root.get(ProgramSchedule_.dayOfWeek), dayOfWeek))
  7. ));
  8. }

并使用以下方式调用它:

  1. programSchedules.findByProgramWeekAndDay(psFdProgram, 1, DayOfWeek.TUESDAY)

这给我带来了以下问题,其中参数2应该是星期几,但我期望它是3,这是Calendar.TUESDAY的星期几值。

  1. ype.descriptor.sql.BasicBinder TRACE binding parameter [1] as [VARCHAR] - [PS-FD]
  2. ype.descriptor.sql.BasicBinder TRACE binding parameter [2] as [INTEGER] - [1]

我正在使用Spring JPA。

转换器如下所示:

  1. @Component
  2. @Converter(autoApply = true)
  3. public class DayOfWeekConverter implements AttributeConverter<DayOfWeek, Integer> {
  4. @Override
  5. public Integer convertToDatabaseColumn(final DayOfWeek dayOfWeek) {
  6. if (dayOfWeek == null) {
  7. return null;
  8. } else if (DayOfWeek.SUNDAY == dayOfWeek) {
  9. return Calendar.SUNDAY;
  10. } else if (DayOfWeek.MONDAY == dayOfWeek) {
  11. return Calendar.MONDAY;
  12. } else if (DayOfWeek.TUESDAY == dayOfWeek) {
  13. return Calendar.TUESDAY;
  14. } else if (DayOfWeek.WEDNESDAY == dayOfWeek) {
  15. return Calendar.WEDNESDAY;
  16. } else if (DayOfWeek.THURSDAY == dayOfWeek) {
  17. return Calendar.THURSDAY;
  18. } else if (DayOfWeek.FRIDAY == dayOfWeek) {
  19. return Calendar.FRIDAY;
  20. } else if (DayOfWeek.SATURDAY == dayOfWeek) {
  21. return Calendar.SATURDAY;
  22. } else {
  23. throw new IllegalStateException();
  24. }
  25. }
  26. @Override
  27. public DayOfWeek convertToEntityAttribute(final Integer dbValue) {
  28. if (dbValue == null) {
  29. return null;
  30. } else if (Calendar.SUNDAY == dbValue) {
  31. return DayOfWeek.SUNDAY;
  32. } else if (Calendar.MONDAY == dbValue) {
  33. return DayOfWeek.MONDAY;
  34. } else if (Calendar.TUESDAY == dbValue) {
  35. return DayOfWeek.TUESDAY;
  36. } else if (Calendar.WEDNESDAY == dbValue) {
  37. return DayOfWeek.WEDNESDAY;
  38. } else if (Calendar.THURSDAY == dbValue) {
  39. return DayOfWeek.THURSDAY;
  40. } else if (Calendar.FRIDAY == dbValue) {
  41. return DayOfWeek.FRIDAY;
  42. } else if (Calendar.SATURDAY == dbValue) {
  43. return DayOfWeek.SATURDAY;
  44. } else {
  45. throw new IllegalArgumentException(String.format("dbValue=%d is not valid", dbValue));
  46. }
  47. }
  48. }

我用以下方式注释了dayOfWeek:

  1. @Id
  2. @Column(name = "Day", nullable = false)
  3. @Convert(converter = DayOfWeekConverter.class) // I had it without this one as well
  4. private DayOfWeek dayOfWeek;

这不仅限于条件查询,它也在JPQL查询中发生:

  1. @Query("from ProgramSchedule p where p.program = :program and week = :week and dayOfWeek = :dayOfWeek")
  2. Optional<ProgramSchedule> findByProgramWeekAndDay(final Program program, int week, final DayOfWeek dayOfWeek);

产生了以下结果:

  1. where
  2. programsch0_.Program=?
  3. and programsch0_.Week=?
  4. and programsch0_.Day=?
  5. ype.descriptor.sql.BasicBinder TRACE binding parameter [1] as [VARCHAR] - [PS-FD]
  6. ype.descriptor.sql.BasicBinder TRACE binding parameter [2] as [INTEGER] - [1]
  7. 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.

  1. default Optional&lt;ProgramSchedule&gt; findByProgramWeekAndDay(final Program program, int week, final DayOfWeek dayOfWeek) {
  2. return findOne(((root, query, cb) -&gt;
  3. cb.and(
  4. cb.equal(root.get(ProgramSchedule_.program), program),
  5. cb.equal(root.get(ProgramSchedule_.week), week),
  6. cb.equal(root.get(ProgramSchedule_.dayOfWeek), dayOfWeek))
  7. ));
  8. }

And calling it with

  1. 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.

  1. ype.descriptor.sql.BasicBinder TRACE binding parameter [1] as [VARCHAR] - [PS-FD]
  2. ype.descriptor.sql.BasicBinder TRACE binding parameter [2] as [INTEGER] - [1]

I'm using Spring JPA

The converter looks like this

  1. @Component
  2. @Converter(autoApply = true)
  3. public class DayOfWeekConverter implements AttributeConverter&lt;DayOfWeek, Integer&gt; {
  4. @Override
  5. public Integer convertToDatabaseColumn(final DayOfWeek dayOfWeek) {
  6. if (dayOfWeek == null) {
  7. return null;
  8. } else if (DayOfWeek.SUNDAY == dayOfWeek) {
  9. return Calendar.SUNDAY;
  10. } else if (DayOfWeek.MONDAY == dayOfWeek) {
  11. return Calendar.MONDAY;
  12. } else if (DayOfWeek.TUESDAY == dayOfWeek) {
  13. return Calendar.TUESDAY;
  14. } else if (DayOfWeek.WEDNESDAY == dayOfWeek) {
  15. return Calendar.WEDNESDAY;
  16. } else if (DayOfWeek.THURSDAY == dayOfWeek) {
  17. return Calendar.THURSDAY;
  18. } else if (DayOfWeek.FRIDAY == dayOfWeek) {
  19. return Calendar.FRIDAY;
  20. } else if (DayOfWeek.SATURDAY == dayOfWeek) {
  21. return Calendar.SATURDAY;
  22. } else {
  23. throw new IllegalStateException();
  24. }
  25. }
  26. @Override
  27. public DayOfWeek convertToEntityAttribute(final Integer dbValue) {
  28. if (dbValue == null) {
  29. return null;
  30. } else if (Calendar.SUNDAY == dbValue) {
  31. return DayOfWeek.SUNDAY;
  32. } else if (Calendar.MONDAY == dbValue) {
  33. return DayOfWeek.MONDAY;
  34. } else if (Calendar.TUESDAY == dbValue) {
  35. return DayOfWeek.TUESDAY;
  36. } else if (Calendar.WEDNESDAY == dbValue) {
  37. return DayOfWeek.WEDNESDAY;
  38. } else if (Calendar.THURSDAY == dbValue) {
  39. return DayOfWeek.THURSDAY;
  40. } else if (Calendar.FRIDAY == dbValue) {
  41. return DayOfWeek.FRIDAY;
  42. } else if (Calendar.SATURDAY == dbValue) {
  43. return DayOfWeek.SATURDAY;
  44. } else {
  45. throw new IllegalArgumentException(String.format(&quot;dbValue=%d is not valid&quot;, dbValue));
  46. }
  47. }
  48. }

I annotated dayOfWeek as follows

  1. @Id
  2. @Column(name = &quot;Day&quot;, nullable = false)
  3. @Convert(converter = DayOfWeekConverter.class) // I had it without this one as well
  4. private DayOfWeek dayOfWeek;

It's not limited to criteria queries either, it also occurs with JPQL queries:

  1. @Query(&quot;from ProgramSchedule p where p.program = :program and week = :week and dayOfWeek = :dayOfWeek&quot;)
  2. Optional&lt;ProgramSchedule&gt; findByProgramWeekAndDay(final Program program, int week, final DayOfWeek dayOfWeek);

yields

  1. where
  2. programsch0_.Program=?
  3. and programsch0_.Week=?
  4. and programsch0_.Day=?
  5. ype.descriptor.sql.BasicBinder TRACE binding parameter [1] as [VARCHAR] - [PS-FD]
  6. ype.descriptor.sql.BasicBinder TRACE binding parameter [2] as [INTEGER] - [1]
  7. ype.descriptor.sql.BasicBinder TRACE binding parameter [3] as [INTEGER] - [1]

答案1

得分: 1

@Id@Convert不能同时使用,所以你需要使用@IdClass,像这样:

  1. @Entity
  2. @IdClass(MyEntity.class)
  3. public class MyId {
  4. @Id
  5. private DayOfWeek dayOfWeek;
  6. ...
  7. }
  8. public class MyEntity implements Serializable {
  9. @Column(name = "Day")
  10. @Convert(converter = DayOfWeekConverter.class)
  11. private DayOfWeek dayOfWeek;
  12. }

编辑 根据文档,上面的代码也不起作用,所以我寻找了一种解决方法,找到了这个:

  1. @Entity
  2. public class MyEntity {
  3. @EmbeddedId
  4. private DayOfWeek dayOfWeek;
  5. ...
  6. }
  7. @Embeddable
  8. public static class Id {
  9. @Column(name = "Day")
  10. @Convert(converter = DayOfWeekConverter.class)
  11. private DayOfWeek dayOfWeek;
  12. }
英文:

@Id and @Convert cannot be used together, so you have to use an @IdClass, like so:

  1. @Entity
  2. @IdClass(MyEntity.class)
  3. public class MyId {
  4. @Id
  5. private DayOfWeek dayOfWeek;
  6. ...
  7. }
  8. public class MyEnity implements Serializable {
  9. @Column(name = &quot;Day&quot;)
  10. @Convert(converter = DayOfWeekConverter.class)
  11. private DayOfWeek dayOfWeek;
  12. }

EDIT According to docs the above code also doesn't work, so I looked for a workaround and found this:

  1. @Entity
  2. public class MyEntity {
  3. @EmbeddedId
  4. private DayOfWeek dayOfWeek;
  5. ...
  6. }
  7. @Embeddable
  8. public static class Id {
  9. @Column(name = &quot;Day&quot;)
  10. @Convert(converter = DayOfWeekConverter.class)
  11. private DayOfWeek dayOfWeek;
  12. }
  13. </details>

huangapple
  • 本文由 发表于 2020年8月8日 18:19:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/63314274.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定