13

我为如何在 Play 中使用 JPA 存储 HashMap 苦苦挣扎了将近一周。存储所有其他属性,只有 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并且没有配置任何东西,除了删除数据库设置前面的“#”(注释标记))。

On Play 文档说:“ Play 2.0 中没有内置的 JPA 实现”。会是这样吗?

更新:我做了一些研究,并说这可能是因为我使用的是 Play - H2 的默认数据库。我尝试使用 MySQL -视频如何做到这一点,但它再次只保存了 id 和 url。我查看了 MySQL 数据库和表,类名只有 2 个属性(id 和 url),没有我的 HashMap 的痕迹。

更新 2:添加了一个打印屏幕 -带有数据库查询。

更新3:来自 Play 的示例“computer-database-jpa”工作正常,所以 JPA 应该没问题,但该示例没有使用 Map (HashMap)。我什至用 EclipseLink 更改了休眠模式,但仍然无法正常工作。:((虽然,所有基本类型属性都在数据库中)

4

2 回答 2

4

以下是我使用您的模型实现 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>();
}

我决定接受 Eric 的建议,即为 Tag 创建一个完整的模型,以便轻松地进行查询,但有时能够使用 Map 的功能会有很大帮助。这也适用于 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

于 2013-07-12T18:36:22.163 回答
1

我认为这里真正的问题是:
为什么将这些标签存储在地图中?我想这将是某种key->value配对,例如"author"->"John Smith","theme"->"Animals"等,对吧?

恕我直言,你应该有一个类型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、单元测试等。

此外,这使您可以轻松地进行一些有用的查询,例如:

  • 按标签搜索图像
  • 列出现有标签
  • 列出名称为“作者”的标签
  • ...
于 2013-06-02T09:23:06.697 回答