当前位置: 首页 > 知识库问答 >
问题:

JPA映射一个可嵌入类,其中包含映射

充培
2023-03-14

我正在使用JPA编写一个Java EE应用程序,它需要国际化。为此,我创建了一个名为multilingarstring的类,该类将语言与字符串相关联(并扩展了HashMap

/**
 * 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
@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)        |           |

这几乎是好事。

此实现的问题是重复MultilgualString字段上的@瞬态getStrings()方法上的@ElementCollection@MapKeyJoinColzo(每次需要在数据库BTW中映射MultilgualString时都必须重新编写:每个实体类至少1个)。在我看来,它使代码变得丑陋且更难维护。

另一件事是:它是通过映射将语言与字符串相关联的实体。应该有一个类将两者关联起来:比如我在这里读到的本地化字符串

因此,我希望多语言字符串的行为类似于值类型,因此我不需要重复上面提到的多个注释,也不需要实现本地化字符串。

下面是我到目前为止的想法。它不起作用,GlassFish不会从这样的映射开始,我总是得到一个java。util。当EclipseLink看到多语言字符串映射时,无接触元素异常。

@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;
}

因此,我希望通过此实现获得与上面所述相同(或尽可能接近)的数据库映射。这可能吗?我读到一个可嵌入类不应该包含另一个(可嵌入类的集合),但在这里,我就是这样。

我读了几篇文章和博客,没有发现这么多类似的情况(“具有实体键和可嵌入值的JPA映射”)

实际上,我正在尝试做类似的事情,只是我的map值是一个可嵌入的类。我在StackOverflow上发现了一个类似的情况(除了我希望他的根类是可嵌入的),我测试了一个答案(运气不好),但它没有“标记为答案”,这个问题也没有太大成功。

共有1个答案

卢志行
2023-03-14

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

@Aspect
public class LocalizationAspect {

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

通过微小的更改,您可以将其应用于返回实体的集合...

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

 类似资料:
  • 我一直试图通过一个名为Guardian的中间类映射两个用户之间的一些“OneToOne”关系。当我试图检索一个用户(和他的监护人)时,从Glassfish(Open edition V4.0)返回一个内部服务器错误。但是,日志中没有显示任何类型的堆栈跟踪或任何错误。我怀疑问题是我在JPA类中的映射。 启动服务器时,我得到两个与Guardian类有关的警告,但我并不真正理解: 警告:映射到元素[me

  • 下午好: 我最近创建了一个类“X”,它包含一个单一属性“network”,定义为一个映射,使用字符串作为键,另一个映射作为值(double map)。对于此类,将使用“hashmap”实现。 该类大致如下所示: 但是,当我执行函数中包含的network.put指令时,编译器会自动检测到一个错误:“表达式预期”。如果可能,我想知道在向映射中添加新的键值元素时是否使用了错误的语法,或者是否是映射的初始

  • 我有一个实体Person,它由name属性组成 我不想在一个额外的表中存储“name”...我将name标记为transient,这样它就不会存储在基础数据库中。 我想要的是将属性“name”映射到数据库中的列“first_name”和“last_name”。 例如,我可以像那样创建一个人 如何实现映射,使基础表包含两个附加列first_name和last_name,内容是从name属性获得的字符

  • 主要内容:@OneToOne示例,程序输出结果一对一映射映射表示一个单值关联,其中一个实体的实例与另一个实体的实例相关联。在这种类型的关联中,源实体的一个实例可以映射到目标实体的一个实例。 完整的项目目录结构如下所示 - @OneToOne示例 在这个例子中,我们将创建一个学生和图书库之间的一对一关系,这样一个学生只能发放一种类型的图书。 这个例子包含以下步骤 - 第1步: 在包下创建一个实体类,在包下创建一个实体类,含学生ID()和学生姓名

  • 问题内容: 我一直在研究一个非常简单的JPA示例,并试图将其调整为现有数据库。但是我无法克服这个错误。(下面。)这只是我没看到的一些简单的事情。 在下面的DocumentManager类中(一个简单的servlet,因为这是我的目标),它做了两件事: 插入一行 返回所有行 插入效果很好-一切都很好。问题出在检索上。我尝试了各种参数值,但没有走运,并且尝试了各种更复杂的类注释(如列类型),但都没有成

  • 下面是Main中的随机客户端列表 第二类:产品(字符串名称、枚举类别、BigDecimal价格) 目标->预期结果:在类Main中,创建类Shopping的实例,其中属性是具有 的映射,并用随机数据//integer-购买了多少产品 null null