我正在尝试通过 JPA 实现一种简单的国际化方法。我想要一个翻译后的字符串表,我可以在多个表的多个字段中引用它。因此,所有表中出现的所有文本都将替换为对已翻译字符串表的引用。结合语言 id,这将在翻译字符串表中为该特定字段提供一个唯一的行。例如,考虑一个具有实体 Course 和 Module 的模式,如下所示:-
类(class) int course_id, 整数名称, 内部描述
模块 int module_id, 内部名称
course.name、course.description 和 module.name 都引用了翻译字符串表的 id 字段:-
TranslatedString 内部编号, 字符串朗, 字符串内容
这一切看起来很简单。我为所有可以国际化的字符串得到一个表,并且该表用于所有其他表。
我如何使用 eclipselink 2.4 在 JPA 中执行此操作?
我看过嵌入式 ElementCollection,ala this... JPA 2.0: Mapping a Map - 这不完全是我想要的,因为它看起来像是将翻译后的字符串表与拥有表的 pk 相关联。这意味着我每个实体只能有一个可翻译的字符串字段(除非我将新的连接列添加到可翻译的字符串表中,这违背了这一点,这与我试图做的相反)。我也不清楚这将如何跨实体工作,大概每个实体的 ID 都必须使用数据库范围的序列来确保可翻译字符串表的唯一性。
顺便说一句,我尝试了该链接中列出的示例,但它对我不起作用 - 一旦实体添加了 localizedString 映射,坚持它会导致客户端崩溃但服务器上没有明显错误边,数据库中没有任何内容:S
到目前为止,我已经在房子周围转了大约 9 个小时,我看过这个 Internationalization with Hibernate这似乎试图做与上面的链接相同的事情(没有表定义很难看出他取得了什么成就)。在这一点上,我们将不胜感激...
编辑 1 - 重新 AMS anwser 下面,我不确定是否真的解决了这个问题。在他的示例中,它将描述文本的存储留给了其他一些进程。这种方法的想法是实体对象采用文本和语言环境,这(不知何故!)最终出现在可翻译字符串表中。在我给出的第一个链接中,这个人试图通过使用嵌入式 map 来做到这一点,我认为这是正确的方法。他的方法虽然有两个问题——一个似乎行不通!两个如果它确实有效,它将 FK 存储在嵌入式表中而不是相反(我想,我无法运行它所以我无法确切地看到它是如何持续存在的)。我怀疑正确的方法最终是用 map 引用代替每个需要翻译的文本( map 是语言环境-> 内容),但我看不出如何以允许在一个实体中使用多个 map 的方式做到这一点(在可翻译字符串表中没有对应的多列)...
最佳答案
(我是 Henno,他回复了 hwellman 的博客。)我最初的方法与您的方法非常相似,并且它完成了工作。它满足任何实体的任何字段都可以引用具有通用数据库表的本地化字符串映射的要求,而不必引用其他更具体的表。事实上,我还将它用于我们产品实体中的多个字段(名称、描述、详细信息)。我还有一个“问题”,即 JPA 生成的表仅包含一个主键列和一个用于引用此 ID 的值的表。使用 OpenJPA,我不需要虚拟列:
public class StringI18N {
@OneToMany(mappedBy = "parent", cascade = ALL, fetch = EAGER, orphanRemoval = true)
@MapKey(name = "locale")
private Map<Locale, StringI18NSingleValue> strings = new HashMap<Locale, StringI18NSingleValue();
...
OpenJPA 只是将 Locale 存储为字符串。因为我们真的不需要额外的实体 StringI18NSingleValue,所以我认为使用 @ElementCollection 的映射更优雅一些。
但有一个问题您必须注意:您是否允许与多个实体共享 Localized 实体,以及当拥有实体被删除时如何防止孤立的 Localized 实体?仅仅使用 cascade all 是不够的。我决定尽可能将 Localized 视为“值对象”,并且不允许它与其他实体共享,这样我们就不必考虑对同一个 Localized 的多个引用,我们可以安全地使用孤儿移除。所以我的本地化字段映射如下:
@OneToOne(cascade = ALL, orphanRemoval = true)
根据我的用例,我还使用 fetch = EAGER/LAZY 和 optional = false 或 true。使用 optional = false 时,我使用 @JoinColumn(nullable=false) 因此 OpenJPA 在连接列上生成非空约束。
每当我确实需要将 Localized 复制到另一个实体时,我不会使用相同的引用,而是创建一个具有相同内容但还没有 ID 的新 Localized 实例。否则你可能很难调试 changin 如果你不这样做你仍然与多个实体共享一个实例的问题,你可能会遇到令人惊讶的错误,其中更改本地化字符串会更改另一个实体的另一个字符串。
目前一切顺利,但在实践中我发现 OpenJPA 在选择包含一个或多个本地化字符串的实体时有 N+1 个选择问题。它不能有效地获取元素集合(我将其报告为 https://issues.apache.org/jira/browse/OPENJPA-1920 )。该问题可能通过使用 Map
其他 JPA 提供程序可能有类似的 N+1 选择问题。如果您关心获取类别的性能,我会检查用于获取类别的查询数量是否取决于实体数量。我知道使用 Hibernate 你可以强制批量获取或子选择来解决这类问题。我也知道 EclipseLink 具有类似的功能,这些功能可能有效也可能无效。 出于解决这个性能问题的绝望,我实际上不得不接受一个我不太喜欢的设计:我只是为我必须支持的每种语言添加一个 String 字段到 Localised。对我们来说这是可能的,因为我们目前只需要支持几种语言。这导致只有一个(非规范化)本地化表。然后,JPA 可以在查询中高效地加入本地化表,但这对于许多语言来说都无法很好地扩展,并且不支持任意数量的语言。为了可维护性,我保持 Localized 的外部接口(interface)不变,只是将实现从 Map 更改为 field-per-language,以便我们将来可以轻松切换回来。
关于java - 用于国际化的 JPA 数据库结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13426273/
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
当我使用has_one时,它工作得很好,但在has_many上却不行。在这里您可以看到object_id不同,因为它运行了另一个SQL来再次获取它。ruby-1.9.2-p290:001>e=Employee.create(name:'rafael',active:false)ruby-1.9.2-p290:002>b=Badge.create(number:1,employee:e)ruby-1.9.2-p290:003>a=Address.create(street:"123MarketSt",city:"SanDiego",employee:e)ruby-1.9.2-p290
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我