简体   繁体   中英

How to update an entity in jpa?

I am doing it following way. It's making me feel sick!

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;
    }
}

Any suggestions to avoid this spaghetti code ?

BTW, writing this code is a hard work!

EDIT

BTW, I don't think the em.merge is ready for this. See here

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

It mentioned the detached object , but the update model just got a piece of date. So, if I merge the model, all of model's value will apply to entity.(eg password, which I don't want to update, and the editTo should not touch the password.)

Now, the update looks like this.

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;
}

Here is 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;
    }
}

This one is better, because

  • It's type safe
  • Easy to filter/choose property to merge

It include

I try my best, this is the best I can do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM