我有一个名为 inputPeriod 的自定义 JSF 输入组件,它旨在输入日期周期。每个时期都有一个从和到日期。组件的功能是通过 Javascript 实现的,它会生成一个 JSON 字符串并将其提交给组件。输入组件然后使用默认转换器将 JSON 周期转换为 Period 对象列表并将它们设置在我的托管 bean 上。这一切都完美无缺。
我遇到的问题的根源是,现在我想将相同的组件与 EJB 实体一起使用。我有一个与 BannerPeriod 实体具有一对多关系的 Banner 实体。BannerPeriod 实体的每个实例都有一个 from(开始)和 to(结束)日期,就像我在输入组件中使用的现有 Period 对象一样。我为此实现了一个新的转换器:
@ManagedBean
@RequestScoped
public class BannerPeriodConverter implements Converter {
@Override
public Object getAsObject(FacesContext fc, UIComponent uic, String str) {
if (str != null) {
Date from = null, to = null;
try {
JSONObject period = new JSONObject(str);
if (period.has("from")) {
from = new Date(period.getLong("from"));
}
if (period.has("to")) {
to = new Date(period.getLong("to"));
}
} catch (JSONException ex) {
throw new ConverterException(ex);
}
BannerPeriod bp = new BannerPeriod();
bp.setBegins(from);
bp.setEnds(to);
return bp;
}
return null;
}
@Override
public String getAsString(FacesContext fc, UIComponent uic, Object o) {
if (o != null && o instanceof BannerPeriod) {
BannerPeriod bp = (BannerPeriod) o;
JSONObject period = new JSONObject();
try {
period.put("from", bp.getBegins() != null ? bp.getBegins().getTime() : (Object) null);
period.put("to", bp.getEnds() != null ? bp.getEnds().getTime() : (Object) null);
} catch (JSONException ex) {
throw new ConverterException(ex);
}
return period.toString();
}
return "";
}
}
转换器与组件配合良好。我遇到的问题是,当我编辑具有现有横幅时段的横幅时,实体会丢失其主键。因此,当我提交表单时,我没有更新现有期间,而是得到一个重复的异常,或者再次创建现有期间,在数据库中进行实际重复。
所以我的问题是,我能做些什么来避免这种情况?我的猜测是输入组件需要以某种方式保留现有实体上的主键,但我怎样才能最好地制作这样的东西呢?目前,输入组件与实体和我的 EJB 项目完全分离。输入组件甚至位于它自己的 JSF 项目中,而上面的转换器位于 EJB 项目中。默认情况下,输入组件使用纯 Period 对象,该对象根本没有主键。它应该继续这样做。
或者也许这应该以其他方式解决?