Подтвердить что ты не робот

Play Framework: решение для хранения карты, ключевое значение с использованием JPA

Я борюсь почти неделю с того, как хранить HashMap, используя JPA в Play. Все остальные атрибуты сохранены, только HashMap имеет нулевые элементы (пуст).

public class ImageModel extends Model {

 @Id
 private String id;
 private String url;

 @ElementCollection(targetClass = java.lang.String.class)
 @MapKeyClass(java.lang.String.class)
 private Map<String,String> tags = new HashMap<>();

 // the method for adding keys and values to the HashMap
 public void add(String key, String value){
    tags.put(key,value);
    this.save();
}

}

Я также попытался аннотировать:

@ElementCollection(fetch=FetchType.LAZY)

Итак, до сих пор я догадываюсь, что я плохо настроил Play. (Я должен сказать, что я использую Play2 и ничего не настроил, кроме удаления "#" (метки комментариев) перед настройками базы данных).

В документации по игре говорится: " В Play 2.0 нет встроенной реализации JPA. Может быть, случай?

Обновление. Я провел некоторое исследование и сказал, что это может быть потому, что я использую базу данных по умолчанию из Play - H2. Я попытался с MySQL - видео, как это сделать, но опять же сохраняет только идентификатор и URL. Я посмотрел в базе данных MySQL, и таблица с именем класса имела только 2 атрибута (id и url), никаких следов моего HashMap.

Update2: добавлен экран печати - с запросом базы данных.

Update3: образец "computer-database-jpa" из Play работает нормально, поэтому JPA должен быть хорошим, но этот образец не использовал карту (HashMap). Я даже сменил спящий режим с EclipseLink, но все еще не работал.:( (хотя все базовые атрибуты типов находятся в базе данных)

4b9b3361

Ответ 1

Вот как я применил HashMap, используя ваши модели.

@Entity
public class ImageModel extends Model {
    //All your fields, etc.

    @ManyToMany(mappedBy = "imagesWithTag")
    @MapKey(name = "name")
    public Map<String,Tag> tags = new HashMap<String,Tag>();
}

@Entity
public class Tag extends Model {
    // All your fields, etc.

    public String name;
    public String value;

    @ManyToMany
    public List<ImageModel> imagesWithTag = new ArrayList<ImageModel>();
}

Я решил пойти с предложением Эрика создать целую модель для Tag, чтобы легко делать запросы, но бывают случаи, когда возможность использования функциональных возможностей Карты очень поможет. Это также должно работать и для EnumMaps.

public void addTag(String tagName, String value) {
    Tag tag = Tag.finderTag.where().eq("name", tagName).eq("value", value).findUnique();
    if(tag == null) {
        tag = Tag.newTag(tagName, value);
    }
    this.tags.put(tag.name, tag);
    this.saveManyToManyAssociations("tags");
}

public static List<ImageModel> getImagesWithTag(String tagName, String tagValue) {

    Tag tag = finderTag.where().eq("name", tagName).eq("value", tagValue).findUnique();

    List<ImageModel> images = new ArrayList<ImageModel>();
    for(ImageModel model : tag.imagesWithTag) {
        images.add(model);
    }
    return images;
}

Я почти ничего не видел в использовании карт в моделях Play Framework, поэтому я решил создать небольшой образец проекта (Play 2.1.1), чтобы поиграть с ним и продемонстрировать использование карт.

https://github.com/Raymond26/play-framework-demos/tree/master/PlayMap

Ответ 2

Я думаю, что реальный вопрос здесь:
Зачем хранить эти теги на карте? Я предполагаю, что это будет какая-то пара key->value вроде "author"->"John Smith", "theme"->"Animals" и т.д. Правильно?

IMHO, у вас должен быть тип Tag:

@Entity
class Tag {
    @Id
    private Long id;
    private String name;
    private String value;
    // getters, setters, hashCode, equals, etc.
    // ...
}

и имеют отношение в ImageModel:

public class ImageModel extends Model {
    // ...
    @ManyToMany
    private Set<Tag> tags;
    // ...
}

Здесь у вас есть сильная типизированная коллекция, которая делает действительно явным, что такое отношение.

Таким образом, вы можете добавить интересный материал на Tag как уникальное ограничение, некоторую проверку (JSR303), дополнительные поля, Javadoc, модульные тесты и т.д.

Кроме того, это позволяет легко выполнять некоторые полезные запросы, например:

  • поиск изображений по тегу
  • список существующих тегов
  • список тегов с именем "автор"
  • ...