用于部分持久性和序列化的Java DTO类设计?

时间:2018-04-24 20:45:15

标签: java hibernate jackson

我有一个包含数百个属性的复杂Java DTO(数据传输对象模式)类。出于说明目的,仅考虑两个

class PointlessExample {
    private int x;
    private int y;
    public ... // getters/setters
}

将此重构为两个类的最佳方法是什么,以便某些属性子集(' x')可以与完整类分开保存,并单独或与完整类一起序列化?

我的简单想法是:

@Entity 
class PointlessBase {
    private int x;
    ...
}
class PointlessExample extends PointlessBase {
    private int y;
    ...
}

然而问题是,对象可以作为完整的类(PointlessExample)开始它们的生命周期,虽然它们总是被保存为PointlessBase,但我有用例来序列化和反序列化为完整或部分对象(包括从完整序列化对象反序列化部分对象)。没有简单的方法可以序列化(通过Jackson)或持久化(通过Hibernate)只有属于PointlessBase对象的PointlessExample字段。或者有吗?

1 个答案:

答案 0 :(得分:0)

DTO通常为painful concept 你使用继承分离属性的想法听起来很好 如果我理解你的要求,你需要这样的东西:

---------------------------------------
| Class            | JSON | Hibernate |
---------------------------------------
| PointlessBase    | YES  | YES       |
---------------------------------------
| PointlessExample | YES  | NO        |
---------------------------------------

Jackson中,您可以自定义反序列化的序列化过程,并且通常忽略来自给定类型或其他过滤器的属性。例如,请参阅我的简单类过滤器:

class ClassIgnoranceIntrospector extends JacksonAnnotationIntrospector {

    private final Class<?> clazz;

    ClassIgnoranceIntrospector(Class<?> clazz) {
        this.clazz = clazz;
    }

    public boolean hasIgnoreMarker(AnnotatedMember m) {
        return m.getDeclaringClass() != clazz;
    }
}

您可以在下面找到如何使用它:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;

import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) throws Exception {
        ObjectMapper baseMapper = new ObjectMapper();
        baseMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        baseMapper.setAnnotationIntrospector(new ClassIgnoranceIntrospector(PointlessBase.class));

        ObjectMapper extendedMapper = new ObjectMapper();
        extendedMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        extendedMapper.setAnnotationIntrospector(new ClassIgnoranceIntrospector(PointlessExample.class));

        List<PointlessBase> list = Arrays.asList(new PointlessBase(), new PointlessExample());
        for (PointlessBase item : list) {
            System.out.println("Base only mapper for class " + item.getClass().getSimpleName() + " " + baseMapper.writeValueAsString(item));
            System.out.println("Extended only mapper for class " + item.getClass().getSimpleName() + " " + extendedMapper.writeValueAsString(item));
        }
    }
}

以上印刷品:

Base only mapper for class PointlessBase {"x":10}
Extended only mapper for class PointlessBase {}
Base only mapper for class PointlessExample {"x":10}
Extended only mapper for class PointlessExample {"y":11}

您可以使用ObjectMapper的不同实例来序列化特定的属性集。如果您不想序列化/反序列化所有属性,请使用默认ObjectMapper

另一个想法是使用Jackson JSON Views。有关如何使用Jackson读取Inheritance with Jackson处理正确继承的更多信息。