简体   繁体   English

Java DTO类设计是否可以部分持久化和序列化?

[英]Java DTO class design for partial persistance and serialization?

I have a complex Java DTO (Data Transfer Object pattern) class with hundreds of properties. 我有一个具有数百个属性的复杂Java DTO(数据传输对象模式)类。 For illustration purposes consider just two 出于说明目的,仅考虑两个

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

What is the best way to refactor this into two classes so that some subset of attributes ('x') can be persisted separately from the full class, and serialized either separately or together with the full class? 将其重构为两类的最佳方法是什么,以便可以将某些属性子集('x')与完整类分开保存,并分别或与完整类一起序列化?

My simple idea was: 我的简单想法是:

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

The problem however, is that objects can start their lifecyle as the full class ( PointlessExample ), and although they would always be persisted as PointlessBase , I have use-cases to serialize and deserialize as either the full or the partial object (including, deserialize a partial object from a full serialized object). 但是,问题在于,对象可以作为完整类( PointlessExample )开始其生命周期,尽管它们将始终作为PointlessBase持久存在,但我有一些用例可以序列化和反序列化为完整或部分对象(包括反序列化)来自完整序列化对象的部分对象)。 There is no easy way to serialize (through Jackson) or persist (through Hibernate) only the PointlessBase fields belonging to a PointlessExample object. 没有简单的方法来序列化(通过Jackson)或保留(通过Hibernate)仅属于PointlessExample对象的PointlessBase字段。 Or is there? 还是在那里?

DTO is generally a painful concept . DTO通常是一个痛苦的概念
Your idea of separating properties using inheritance sounds fine. 您使用继承分离属性的想法听起来不错。
If I understand your requirements, you need something like this: 如果我了解您的要求,则您需要以下内容:

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

In Jackson you can customise process of serialization of deserialization and generally ignore properties which comes from given type or by other filters. Jackson您可以自定义反序列化的序列化过程,并且通常会忽略来自给定类型或其他过滤器的属性。 For example see my simple class filter: 例如看我简单的类过滤器:

class ClassIgnoranceIntrospector extends JacksonAnnotationIntrospector {

    private final Class<?> clazz;

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

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

Below you can find how to use it: 您可以在下面找到如何使用它:

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

Above prints: 以上印刷品:

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}

You can use different instance of ObjectMapper to serialize specific set of properties. 您可以使用ObjectMapper不同实例来序列化特定的属性集。 If you wont to serialize/deserialize all properties use default ObjectMapper . 如果您不想序列化/反序列化所有属性,请使用默认的ObjectMapper

Another idea is using Jackson JSON Views . 另一个想法是使用Jackson JSON Views For more information how to handle properly inheritance with Jackson read Inheritance with Jackson . 有关如何正确处理Jackson 继承的更多信息,请阅读继承Jackson

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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