Как обновить сущность в jpa?

1

Я делаю это следующим образом. Это заставляет меня чувствовать себя больным!

public class CounselInfoServiceImpl
    extends BaseServiceImpl<CounselInfoDao, CounselInfoEntity, Long>
    implements CounselInfoService {

    @Inject
    ClassService classService;

    @Inject
    @Override
    public void setDao(CounselInfoDao dao)
    {
        super.setDao(dao);
    }

    @Override
    public CounselInfoEntity editTo(CounselInfoEntity model)
    {
        CounselInfoEntity entity = id(model.getId());

        if (!Strings.isNullOrEmpty(model.getName()))
        {
            entity.setName(model.getName());
        }

        if (!Strings.isNullOrEmpty(model.getAddress()))
        {
            entity.setAddress(model.getAddress());
        }

        if (!Strings.isNullOrEmpty(model.getEducation()))
        {
            entity.setEducation(model.getEducation());
        }

        if (!Strings.isNullOrEmpty(model.getPhone()))
        {
            entity.setPhone(model.getPhone());
        }

        if (!Strings.isNullOrEmpty(model.getQQ()))
        {
            entity.setQQ(model.getQQ());
        }

        if (!Strings.isNullOrEmpty(model.getRemark()))
        {
            entity.setPhone(model.getPhone());
        }

        if (!Strings.isNullOrEmpty(model.getSchool()))
        {
            entity.setSchool(model.getSchool());
        }

        if (model.getAge() != null)
        {
            entity.setAge(model.getAge());
        }

        if (model.getSex() != null)
        {
            entity.setSex(model.getSex());
        }

        if (model.getClassIntention() != null)
        {                           
            entity.setClassIntention(
                      classService.id(
                            model.getClassIntention().getId()));
        }

        return entity;
    }
}

Любые предложения, чтобы избежать этого spaghetti code?

Кстати, писать этот код - тяжелая работа!

РЕДАКТИРОВАТЬ

Кстати, я не думаю, что em.merge готов к этому. См. Здесь

The EntityManager.merge() operation is used to merge the changes made to a detached object into the persistence context.

Он упомянул detached object, но модель обновления просто получила кусочек даты. Итак, если я объединил модель, все значение модели будет применено к объекту (например, пароль, который я не хочу обновлять, и editTo не должен касаться пароля).

  • 0
    То, что у вас есть, это странный способ сделать. Обычно при использовании приложения для редактирования объекта пользователь использует предварительно заполненную форму, содержащую все поля объекта, изменяет поля, которые должны быть изменены, отправляет эту форму, и все поля, пустые или нет, записываются к сущности. Я никогда не видел форму, в которой оставление поля пустым означает «не изменяйте значение этого атрибута».
  • 0
    Нет пустого поля в форме, потому что я не буду отображать эти поля. Некоторые поля (ы) проверяют чувствительность. Таким образом, пользователь может редактировать только часть всей даты.
Показать ещё 2 комментария
Теги:
optimization
jpa
design

1 ответ

0
Лучший ответ

Теперь обновление выглядит так.

public CounselInfoEntity editTo(CounselInfoEntity model)
{
    CounselInfoEntity entity = id(model.getId());

    List<? extends Attribute<CounselInfoEntity, ?>> editAttrs = Lists.<Attribute<CounselInfoEntity, ?>>newArrayList(CounselInfoEntity_.name,
    CounselInfoEntity_.address,
    CounselInfoEntity_.education,
    CounselInfoEntity_.phone,
    CounselInfoEntity_.QQ,
    CounselInfoEntity_.remark,
    CounselInfoEntity_.school,
    CounselInfoEntity_.age,
    CounselInfoEntity_.sex);

    BeanHelper.merge(entity, model, BeanHelper.skipNullOrEmpty(model, editAttrs));

    if (model.getClassIntention() != null)
    {                           
        entity.setClassIntention(classService.id(model.getClassIntention().getId()));
    }

    return entity;
}

Вот BeanHelper

package me.wener.practices.web.common.util;

import com.google.common.collect.Lists;
import java.lang.reflect.Field;
import java.util.List;
import javax.persistence.metamodel.Attribute;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.reflect.FieldUtils;

@Slf4j
public class BeanHelper
{
    /**
     * 获取 bean 的属性,如果属性不存在或发生异常返回null
     */
    public static Object tryGetProperty(Object bean, String attrName)
    {
        Object property = null;
        try
        {
            Field field = FieldUtils.getField(bean.getClass(), attrName, true);
            property = field.get(bean);
        } catch (Exception e)
        {
            if (log.isErrorEnabled())
                log.error("Exception when get property " + attrName + " on " + bean, e);
        }
        return property;
    }

    public static <T, A extends Attribute<T, ?>> Object tryGetProperty(T bean, A attr)
    {
        return tryGetProperty(bean, attr.getName());
    }

    public static <T, A extends Attribute<T, ?>> boolean trySetProperty(T bean, A attr, Object value)
    {
        return trySetProperty(bean, attr.getName(), value);
    }

    public static boolean trySetProperty(Object bean, String attrName, Object value)
    {
        boolean failed = false;
        try
        {
            // 对于 chain 的 setter 方法, 必须要使用 force access.
            Field field = FieldUtils.getField(bean.getClass(), attrName, true);
            field.set(bean, value);
        } catch (Exception e)
        {
            if (log.isErrorEnabled())
                log.error("Exception when set property " + attrName + " on " + bean, e);

            failed = true;
        }
        return !failed;
    }

    /**
     * Test the value of search in attrs is make the isNull and isEmpty
     * <p/>
     * isEmpty will apply when value is String
     */
    @SafeVarargs
    public static <E, A extends Attribute<E, ?>> List<A> skip(Object searcher, boolean skipNull, boolean skipEmpty, A... attrs)
    {
        return skip(searcher, skipNull, skipEmpty, Lists.newArrayList(attrs));
    }

    public static <E, A extends Attribute<E, ?>> List<A> skip(Object searcher, boolean skipNull, boolean skipEmpty, List<A> attrs)
    {
        List<A> list = Lists.newArrayList();
        boolean valid;

        for (A attr : attrs)
        {
            Object value = tryGetProperty(searcher, attr.getName());
            valid = skipNull || value != null;

            if (valid && skipEmpty && value instanceof String)
                valid = ((String) value).length() != 0;

            if (valid)
                list.add(attr);
        }
        return list;
    }

    @SafeVarargs
    public static <E, A extends Attribute<E, ?>> List<A> skipNullOrEmpty(Object searcher, A... attrs)
    {
        return skip(searcher, true, true, attrs);
    }

    public static <E, A extends Attribute<E, ?>> List<A> skipNullOrEmpty(Object searcher, List<A> attrs)
    {
        return skip(searcher, true, true, attrs);
    }

    @SafeVarargs
    public static <T, A extends Attribute<T, ?>> T merge(T target, T src, A... attrs)
    {
        return merge(target, src, Lists.newArrayList(attrs));
    }

    public static <T, A extends Attribute<T, ?>> T merge(T target, T src, List<A> attrs)
    {
        for (A attr : attrs)
        {
            String attrName = attr.getName();
            Object value = tryGetProperty(src, attrName);
            trySetProperty(target, attrName, value);
        }

        return target;
    }
}

Это лучше, потому что

  • Это безопасный тип
  • Легко фильтровать/выбирать свойство для слияния

Он включает

Я стараюсь изо всех сил, это лучшее, что я могу сделать.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню