Java Persistence:根据运行时参数连接不同的列

Posted

技术标签:

【中文标题】Java Persistence:根据运行时参数连接不同的列【英文标题】:Java Persistence: join different columns dependent on runtime parameter 【发布时间】:2019-08-05 15:12:15 【问题描述】:

考虑以下示例:

我想使用 JPA/Hibernate 来查询左侧的对象,同时直接加入标签。但是,使用哪个标签列由动态会话参数确定。对于某些用户,它是“英语”,而对于其他用户,它是“德语”。因此,我的联接需要针对仅在运行时在动态变量范围内定义的列。

我看到了以下(理论上的)解决方案:

    之后不要使用连接和查询标签 让连接根据运行时参数寻址列 将语言设为列并使用复合键加入标签(同时提供运行时参数作为复合键的第二部分) 使用视图创建两个不同的翻译表(一个用于德语,一个用于英语);使用 runtime 参数动态加入不同的表

虽然解决方案 1 是可行的,但它效率低下并且涉及大量样板代码。另一方面,我无法为 2-4 提出切实可行的解决方案。

此外,鉴于标签必须由数据库管理 - 这种用例的最佳实践解决方案是什么?

【问题讨论】:

'我的联接需要定位一个仅在运行时在动态变量范围内定义的列' - 我不知道如何。你不是一直加入Label_ID = ID吗? 附带说明一下,翻译多久会更改一次?除非可以从您的应用程序外部修改它们,否则我会认真考虑将它们缓存在内存中 @crizzis 是的,我们总是加入 Label_ID = ID。问题在于使用两者(德语/英语)的哪个数据列来填充属性。这些字符串实际上来自我们的应用程序之外,这就是我们需要数据库中的数据的原因。 【参考方案1】:

如果有一个带有某种语言代码的参数,我假设这个问题可以用CASE子句来解决,类似这样:

SELECT t0.id, t0.location, CASE WHEN (?1 = 1) THEN t1.english ELSE t1.german END AS label 
FROM Location t0  INNER JOIN Translation t1  ON (t0.label_id = t1.id)

并且可以使用FluentJPA构建查询:

public List<TranslatedLocation> getTranslatedLocations(int langCode) 
    FluentQuery query = FluentJPA.SQL((Location l,
                                       Translation t) -> 

        String trans = CASE(WHEN(langCode == 1).THEN(t.getEnglish())
                                               .ELSE(t.getGerman())).END();
        String label = alias(trans, TranslatedLocation::getLabel);

        SELECT(l.getId(), l.getLocation(), label);
        FROM(l).JOIN(t).ON(l.getTranslation() == t);

    );

    return query.createQuery(em, TranslatedLocation.class).getResultList();

生成的 SQL:

SELECT t0.id, t0.location,
CASE WHEN (?1 = 1) THEN t1.english ELSE t1.german END AS label

FROM Location t0  INNER JOIN Translation t1  ON (t0.label_id = t1.id)

实体声明:

@Entity
@Data //lombok
public static class Location 
    @Id
    private int id;
    private String location;

    @ManyToOne
    @JoinColumn(name = "label_id")
    private Translation translation;


@Entity
@Data //lombok
public static class Translation 
    @Id
    private int id;
    private String english;
    private String german;


@Tuple
@Getter //lombok
public static class TranslatedLocation 
    @Id
    private int id;
    private String location;
    private String label;

【讨论】:

以上是关于Java Persistence:根据运行时参数连接不同的列的主要内容,如果未能解决你的问题,请参考以下文章

关于 keepalived+lvs 中参数 persistence_timeout 的说明

JPA的配置文件persistence.xml参数详解

创建没有 persistence.xml 配置文件的 JPA EntityManager

根据运行时会话值从 Autofac 解析服务实现

休眠 5 - java.lang.NoSuchMethodError: javax.persistence.Table.indexes()

persistence.xml 从 .properties 文件导入数据库参数值