AWS DynamoDB Java SDK, альтернатива аннотациям

Я хочу избежать использования аннотаций DynamoDB в классе, но по-прежнему иметь возможность использовать преобразователь для записи и чтения из DynamoDB. Я использую Java SDK для чтения и записи из DynamoDB (используя предоставленный файл DynamoDBMapper.

Скажи, что у меня есть это Model.java

@DynamoDBTable(tableName="Model")
public class Model {

    private Integer id;
    private String title;

    @DynamoDBHashKey(attributeName="ModelId")  
    public Integer getId() { return id;}
    public void setId(Integer id) {this.id = id;}

    @DynamoDBAttribute(attributeName="Title")  
    public String getTitle() {return title; }
    public void setTitle(String title) { this.title = title; }
}

Я бы написал ему как обычно

Model model = new Model();
//... random information

DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(model);

Это нормально, но мой объект домена замусорен специфическими аннотациями DynamoDB. Есть ли способ вместо этого иметь класс, который обертывает объект домена (без каких-либо аннотаций). В приведенном ниже случае я бы искал эффективную реализацию DynamoDBModelWrapper

public class Model {
    private Integer id;
    private String title;

    public Integer getId() { return id;}
    public void setId(Integer id) {this.id = id;}

    public String getTitle() {return title; }
    public void setTitle(String title) { this.title = title; }
}

public class DynamoDBModelWrapper extends Model { ... }

Model model = new Model();
//... random information

DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(DyanamoDBModelWrapper(model));

Здоровья и спасибо


person DWB    schedule 10.01.2018    source источник


Ответы (3)


Это кажется очень плохой идеей. Фактически вам придется заставить все ключи и индексы вашей таблицы иметь одно и то же имя. Модель-оболочка не может просто применить одну и ту же аннотацию к каждому атрибуту модели, она должна знать, какую аннотацию применить к какому атрибуту, что означало бы применение аннотаций к классу модели или, поскольку это не разрешено, форсирование модели class для именования атрибутов определенным образом. Например, ваш атрибут первичного хэш-ключа может называться primaryhashkey.

Также вы не сможете использовать некоторые действительно мощные части DyanmoDBMapper, такие как сложное и произвольное сопоставление данных.

Одна вещь, которую следует упомянуть, это то, что вы могли бы хотя бы привести вещи в порядок. У вас есть лишний текст в вашем классе модели. Вам нужно указать attributeName только в том случае, если имя атрибута вашей модели отличается от атрибута таблицы. Если они совпадают, вы можете просто опустить их. То же самое верно для имени класса модели и tableName. Итак, вы можете сделать:

Table schema:
TableName: Model
Partition Key Attribute: id
Attribute: title

И тогда ваш модельный класс будет выглядеть так

@DynamoDBTable
public class Model {

    private Integer id;
    private String title;

    @DynamoDBHashKey  
    public Integer getId() { return id;}
    public void setId(Integer id) {this.id = id;}

    @DynamoDBAttribute 
    public String getTitle() {return title; }
    public void setTitle(String title) { this.title = title; }
}

Аннотации все еще там, но они выглядят намного аккуратнее.

person F_SO_K    schedule 12.01.2018
comment
Привет, Стю, это имеет смысл, и я решил продолжать использовать аннотации. - person DWB; 28.03.2018

Это не очень хорошее решение (IMO), поэтому я надеялся, что кто-то предложит лучшее, но я сделал следующее:

public class Model {
    private Integer id;
    private String title;

    public Integer getId() { return id;}
    public void setId(Integer id) {this.id = id;}

    public String getTitle() {return title; }
    public void setTitle(String title) { this.title = title; }
}

@DynamoDBTable(tableName="Model")
public class DynamoDBModelWrapper  {

    private final Model model;

    DynamoDBModelWrapper() {
        this.model = new Model();
    }
    DynamoDBModelWrapper(final Model model) {
        this.model = model;
    }

    @DynamoDBHashKey(attributeName="ModelId")  
    public Integer getId() { return model.id;}
    public void setId(Integer id) {model.id = id;}

    @DynamoDBAttribute(attributeName="Title")  
    public String getTitle() {return model.title; }
    public void setTitle(String title) { model.title = title; }
}

Затем вы можете создать экземпляр DynamoDBModelWrapper при сохранении/загрузке из DynamoDB и использовать объект без каких-либо специальных аннотаций Dynamo в остальное время.

Model model = new Model();
//... random information

DynamoDBMapper mapper = new DynamoDBMapper(client);
mapper.save(new DynamoDBModelWrapper(model));
person Andy Nugent    schedule 16.07.2018

Добавьте уровень абстракции доступа к данным между вашим приложением и DynamoDB SDK. У вас могут быть отдельные классы модели домена и базы данных, и уровень доступа к данным может преобразовываться между ними.

Вот как это работает.

Определите интерфейс MyTableDataAccess и реализуйте MyTableDataAccessDynamoDBImpl или назовите его как угодно. Код вашего приложения будет вызывать методы MyTableDataAccess, которые должны быть определены в соответствии с вашим доменом и вариантами использования в бизнесе. MyTableDataAccessDynamoDBImpl будет отвечать за преобразование между моделями домена и базой данных и выполнение фактических вызовов DynaModb.

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

  • Вы можете сделать свои доменные классы неизменяемыми. DynamoDBMapper требует наличия конструктора и сеттеров по умолчанию для всех полей, которые вы хотите прочитать. Имея разные модели домена и базы данных, вы можете сделать модель БД изменяемым POJO, а класс вашего домена может быть неизменным.
  • Если вы когда-либо меняли базы данных, гораздо проще создать новую реализацию вашего уровня доступа к данным в одном месте, чем заменить все ссылки dynamodb в вашем приложении.
  • Это позволяет вам использовать такие функции, как TTL элемента или автоматически сгенерированные поля, не подвергая их воздействию вашего приложения.
person Matthew Pope    schedule 02.08.2018