Класс сети pojo и класс сущности базы данных, как избежать дублирования

Извините, если сомнение слишком концептуально, я немного неопытен...

Я получаю данные JSON из URL-адреса с модификацией, и я также хочу сохранить эти данные в своей базе данных SQLite. Для создания этой базы данных я буду использовать новое сопоставление Room ORM.

Я извлекаю сетевые классы POJO с помощью плагина Android Studio GsonFormat, и он генерирует классы Recipes, Ingredients и Steps ниже. И сгенерируйте несколько классов Room Entity (подробнее ниже)

Как видите, оба набора классов практически идентичны, что приводит к большому количеству повторяющегося кода. Но я также не считаю правильным смешивать использование этих двух наборов классов. И Room запрещает объектным объектам ссылаться друг на друга, поэтому, если я захочу использовать первый набор классов, это будет сложнее...

Я сомневаюсь, как эти случаи обрабатываются в целом?

--- Пожо - Гсону понятно:

public class Recipes {

    private int id;
    private String name;
    private int servings;
    private String image;
    private List<Ingredients> ingredients;
    private List<Steps> steps;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getServings() {
        return servings;
    }

    public void setServings(int servings) {
        this.servings = servings;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public List<Ingredients> getIngredients() {
        return ingredients;
    }

    public void setIngredients(List<Ingredients> ingredients) {
        this.ingredients = ingredients;
    }

    public List<Steps> getSteps() {
        return steps;
    }

    public void setSteps(List<Steps> steps) {
        this.steps = steps;
    }

    @Override
    public String toString() {
        return "Recipes{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", servings=" + servings +
                ", image='" + image + '\'' +
                ", ingredients=" + ingredients +
                ", steps=" + steps +
                '}';
    }
}

class Ingredients {
    private double quantity;
    private String measure;
    private String ingredient;

    public double getQuantity() {
        return quantity;
    }

    public void setQuantity(double quantity) {
        this.quantity = quantity;
    }

    public String getMeasure() {
        return measure;
    }

    public void setMeasure(String measure) {
        this.measure = measure;
    }

    public String getIngredient() {
        return ingredient;
    }

    public void setIngredient(String ingredient) {
        this.ingredient = ingredient;
    }

    @Override
    public String toString() {
        return "Ingredients{" +
                "quantity=" + quantity +
                ", measure='" + measure + '\'' +
                ", ingredient='" + ingredient + '\'' +
                '}';
    }
}

class Steps {

    private int id;
    private String shortDescription;
    private String description;
    private String videoURL;
    private String thumbnailURL;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getShortDescription() {
        return shortDescription;
    }

    public void setShortDescription(String shortDescription) {
        this.shortDescription = shortDescription;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getVideoURL() {
        return videoURL;
    }

    public void setVideoURL(String videoURL) {
        this.videoURL = videoURL;
    }

    public String getThumbnailURL() {
        return thumbnailURL;
    }

    public void setThumbnailURL(String thumbnailURL) {
        this.thumbnailURL = thumbnailURL;
    }

    @Override
    public String toString() {
        return "Steps{" +
                "id=" + id +
                ", shortDescription='" + shortDescription + '\'' +
                ", description='" + description + '\'' +
                ", videoURL='" + videoURL + '\'' +
                ", thumbnailURL='" + thumbnailURL + '\'' +
                '}';
    }
}

--- классы сущностей комнаты

@Entity
public class Recipe {

    @PrimaryKey
    private int id;

    private String name;
    private int servings;
    private String image;

}


@Entity(foreignKeys = @ForeignKey(entity = Recipe.class,
        parentColumns = "id",
        childColumns = "recipeId"))
public class Ingredient {

    @PrimaryKey
    private int id;
    private double quantity;
    private String measure;
    private String ingredient;


    private int recipeId;

}

person alexpfx    schedule 24.05.2017    source источник
comment
Я бы порекомендовал вам разделить их все для разных библиотек (передача данных, постоянство и т. д.), но иметь основной объект домена, который будет работать на уровне вашего бизнес-сервиса. Причина в том, что для разных библиотек могут потребоваться разные реализации DTO: для одних требуются общедоступные методы, для других — конструкторы, для некоторых — методы со специальными именами и т. д. и т. д. Я бы разделил их, чтобы заменить библиотеку в случае нужно без боли.   -  person Lyubomyr Shaydariv    schedule 24.05.2017


Ответы (2)


Вы можете использовать один класс объектов, который удовлетворяет как сопоставлению Gson, так и отображению комнаты.

Например.

@Entity
public class Recipe {
  @PrimaryKey           // Room annotation
  @SerializedName("id") // Gson annotation
  private int id;

  @ColumnInfo(name = "name") // Room annotation
  @SerializedName("name")    // Gson annotation
  private String name;
  ....
}

В процессе компиляции Gson и Room будут искать аннотации для сопоставления с правильными сущностями.
В общем, это обычные объекты POJO со специальными аннотациями, помогающими другим фреймворкам правильно их использовать.

person Quang Nguyen    schedule 24.05.2017
comment
Конечно, это сработает, но со временем все начинает запутываться. - person alexpfx; 24.05.2017
comment
Это поможет вам избежать дублирования и сохранить ваши коды в чистоте. Почему вы думаете, что это будет грязно? - person Quang Nguyen; 25.05.2017
comment
Я думаю, что для классов, которые не являются полностью однородными, и классов со многими атрибутами становится все сложнее управлять по мере роста класса. Но для этого простого примера я реализовал так, как вы сказали, и он отлично работает. - person alexpfx; 30.05.2017
comment
Конечно, мой ответ сосредоточен на вашем вопросе о краткости и удалении повторяющихся кодов, поэтому мы можем вернуться с более оптимизированным решением, если возникнут тонкие проблемы. Кстати, я очень признателен, если вы отметите это как принятый ответ. - person Quang Nguyen; 30.05.2017

Я могу придумать 2 решения, и вы должны рассмотреть компромисс, основанный на целях предполагаемого дизайна вашей системы:

1. Сведя к минимуму дублирование, например, используя один из подходов, перечисленных в этом потоке, при объединении 2 классов, объект ответа и объект сущности теперь тесно связаны. Это нормально, если вы уверены, что все поля в ответе подходят для постоянного использования в качестве объекта Room.

2. Вместо того, чтобы уменьшать дублирование, мы позволяем ему происходить в пользу большей расширяемости.

Обычно в своих проектах я лично предпочитаю второй подход, просто потому, что без прямой зависимости мне не приходится хранить ненужные поля (иногда я храню какое-то поле как метаданные вместо использования Room), и плюс мне не нужно писать код миграции каждый раз, когда изменяется ответ.

person atjua    schedule 05.06.2018