【问题标题】:spring boot - calculated fieldspring boot - 计算字段
【发布时间】:2018-01-01 13:21:26
【问题描述】:

所以,我有一个实体,它有字段 start_date(java.util.Date 是类型)。

我想要另一个字段,它会自动填充与开始日期对应的星期几的整数(如数字 1 代表星期日,2 代表星期一等)。

这是我实体的片段:

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@DateTimeFormat(pattern = "yyyy-MM-dd")
@Temporal(TemporalType.DATE)
private Date start_date;

我尝试通过以下方式添加计算字段:

@Column(name = "weekday")
@Formula("(select dayofweek(l.start_date) from Lesson l where l.id = id)")
private Integer weekDay;

但是,在 H2 控制台中查看课程表时,没有“工作日”这样的列

我还尝试了其他选项 - 没有 @Formula 注释并且使用带有 start_date 参数的设置器,但我猜这个设置器永远不会被调用,因为“工作日”列填充了空值。 这是我尝试用作替代解决方案的 setter:

    public void setWeekDay(Date start_date) {
    Calendar c = Calendar.getInstance();
    c.setTime(start_date);
    this.weekDay = c.get(Calendar.DAY_OF_WEEK);
}

很明显我在这里遗漏了一些东西,可能是因为我还在学习Spring boot......

总而言之-我想在表Lesson中有一列,它是从同一张表的另一列中计算出来的。

【问题讨论】:

  • 另外需要注意的是,time 包是一个比 java.util.Date 或 sql.Date 更完整和更好的系统,它们都以各种方式被破坏。您应该考虑切换到它或 JodaTime。

标签: spring hibernate spring-boot


【解决方案1】:

@Formula 表示您的字段将由您的规则计算。此实体字段不是数据库中的列。该字段是按照指定规则为每个实体计算加载时间的。

如果注释 @Column(name = "weekday") 可以在 @Formula 附近工作,如果您期望加载的实体中的值与 DB 中的值相同,但这里计算的值不同(不一致的情况),您会感到非常困惑。

如果你想从Lesson表中保存值,你应该删除@Formula并使用@EntityListeners({YourEntityJpaCallbacksListener.class})在spring beanYourEntityJpaCallbacksListener中你可以定义标有@PreUpdate@PrePersist的方法并使用相应的操作来将计算值设置为weekday

例如:

@EntityListeners({YourEntityJpaCallbacksListener.class})
@Entity
public class YourEntity{
    // your code
}

@Component
public class YourEntityJpaCallbacksListener {
    @Autowired
    private LessonRepository lessonRepository;

    @PreUpdate
    void preUpdate(YourEntity yourEntity) {
        if (recurrentRuleRepository.exists(yourEntity.getId())) {
            Integer weekDay = lessonRepository.findOne(yourEntity.getId());
            yourEntity.setWeekDay(weekDay);
        }
    }

}

【讨论】:

  • 你说得对,我实际上(最终)设法在不使用@Formula 的情况下解决了这个问题。我创建了一个将数据写入 weekDay 的方法,并且我从 start_date 设置器调用它,所以每次创建或更新 start_date 时都会调用此方法。
  • 感谢您的帮助!您的解决方案似乎更加优雅
  • 很高兴来到这里。您已经解决的任何方式,我认为它可以改善您的体验。
  • 如果对您有帮助,请不要忘记接受这个答案。
  • 我尝试了上面的设置,但没有成功。 LessonRepository 上的 @Autowire 注释对我没有任何作用,因为持久化实体时使用的实体侦听器不是由 Spring 创建的。 (该字段始终为空。)我错过了什么吗?
【解决方案2】:

好的,所以我想我已经设法解决了这个问题。

我删除了@Formula 注释 我创建了一个计算星期几并将其写入 weekDay 的方法。

public void calculateDayOfWeek(){
    Calendar c = Calendar.getInstance();
    c.setTime(start_date);
    this.weekDay = c.get(Calendar.DAY_OF_WEEK);
}

我把它放在 start_date setter 里面:

public void setStart_date(Date start_date) {

    this.start_date = start_date;
    calculateDayOfWeek();
}

所以现在,每当 start_date 创建或更新时,它都会更新(或创建)weekDay 的值。

【讨论】:

    猜你喜欢
    • 2018-02-16
    • 2018-06-16
    • 1970-01-01
    • 1970-01-01
    • 2022-08-17
    • 2021-11-30
    • 2018-02-07
    • 2012-10-11
    • 1970-01-01
    相关资源
    最近更新 更多