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

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

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&lt;ProgramSchedule&gt; findByProgramWeekAndDay(final Program program, int week, final DayOfWeek dayOfWeek) {

        return findOne(((root, query, cb) -&gt;
            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&lt;DayOfWeek, Integer&gt; {

    @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(&quot;dbValue=%d is not valid&quot;, dbValue));
        }
    }
}

I annotated dayOfWeek as follows

    @Id
    @Column(name = &quot;Day&quot;, 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(&quot;from ProgramSchedule p where p.program = :program and week = :week and dayOfWeek = :dayOfWeek&quot;)
Optional&lt;ProgramSchedule&gt; 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 = &quot;Day&quot;)
@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 = &quot;Day&quot;)
@Convert(converter = DayOfWeekConverter.class)
private DayOfWeek dayOfWeek;
}
</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:

确定