繁体   English   中英

JPA映射一个包含Map的Embeddable类<Entity, Embeddable>

[英]JPA map an Embeddable class which contains a Map<Entity, Embeddable>

我正在使用JPA编写Java EE应用程序,并且需要对其进行国际化。 为此,我创建了一个名为MultilingualString的类,该类将LanguageString相关联(因此扩展了HashMap<Language, String> ),如下所示:

/**
 * This class is mapped to the database thanks
 * to the Locale.toLanguageTag() method
 * and Locale.fromLanguageTag(String) constructor
 */
public class Language {
    public Locale locale;

    /* Getters, Setters ... */  
}

/**
 * NB : This class extends HashMap to override the put method
 * which needs to ignore putting null values instead of throwing
 * a NullPointerException
 */
public class MultilingualString extends HashMap<Language, String> {
    public Map<Language, String> getStrings() {
        return (this);
    }

    /* ... */
}

现在,假设我们有一个Entity ,该Entity名称取决于Language

@Entity
@Access(AccessType.PROPERTY)
public class Entity {
    private Long id;
    private MultilingualString name;

    @Id
    public Long getId() { ... }

    @Transient
    public MultilingualString getName() { ... }

    @ElementCollection
    @MapKeyJoinColumn(name = "language_id")
    public Map<Language, String> getStrings() {
        return (this.name.getStrings());
    }

    /* ... */
}

此代码产生以下数据库架构:

Language        :
    id          | bigint                        | NOT NULL  | primary key
    languageTag | character varying(255)        |           |
---------------------------------------------------------------------------------------------------
Entity          :
    id          | bigint                        | NOT NULL  | primary key
---------------------------------------------------------------------------------------------------
Entity_strings  :
    entity_id   | bigint                        |           | foreign key references Entity(id)
    language_id | bigint                        |           | foreign key references Language(id)
    string      | character varying(255)        |           |

哪个好

此实现的问题是,在MultilingualString字段上重复@Transient ,在getStrings()方法上重复@ElementCollection @MapKeyJoinColumn getStrings()每次需要在数据库BTW中映射MultilingualString ,都必须重新编写:至少1个/实体类)。 在我看来,它使代码难看且难以维护。

另一件事是:是通过MapLanguageString关联的Entity 应该有一个将它们都关联起来的类:如我在这里所读,说一个LocalizedString

所以我希望MultilingualString表现得像一个值类型,所以我不需要重复上面提到的多个注释并实现LocalizedString

以下是我到目前为止提出的内容。 它不起作用,GlassFish不会以这样的映射开始,当EclipseLink看到MultilingualString映射时,我总是得到java.util.NoSuchElementException

@Embeddable
public class LocalizedString {
    @ManyToOne
    private Language language;
    private String string;
}

@Embeddable
public class MultilingualString extends HashMap<Language, LocalizedString> {

    /**
     * Here I lost myself in all the available annotations
     * and tried thousands of permutation, but always the same exception
     * @MapKeyJoinColumn ?
     * @MapKeyClass ?
     * @CollectionTable ?
     * ...
     */
    @ElementCollection
    public Map<Language, LocalizedString> getStrings() {
        return (this);
    }
}

@Entity
public class Entity {
    @Id
    private Long id;
    @Embedded
    private MultilingualString name;
}

因此,我希望通过这种实现,获得与上面相同的(或最可能的)数据库映射。 那有可能吗? 我读到一个Embeddable类不应包含另一个(的集合) Embeddable类,但是在这里,对我来说就是这种情况。

我读了几篇文章和博客,但没有发现如此多的情况(“带有实体键和可嵌入值的JPA映射”)

实际上,除了我的地图值是Embeddable类之外,我正在尝试执行与此类似的操作。 我在StackOverflow上发现了一种类似的情况 (只是我希望他的Root类是Embeddable ),我测试了一个答案(没有运气),但是没有“被标记为答案”,并且这个问题没有太多成功。

这是可以处理您实体的本地化的方面的示例:

@Aspect
public class LocalizationAspect {

    @AfterReturning(
            pointcut = "@within(MyManager) && execution(MyEntity methodThatReturnsEntity(..))",
            returning = "entity"
    )
    public void localizeMyEntity(MyEntity entity) {
        localize(entity);
    }
}

稍作更改,您就可以将其应用于返回的实体的集合...

localie()使用实体ID在返回结果之前导航本地化信息并将其注入该实体。

暂无
暂无

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

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