在 java 中访问父 class 中的子常量

accessing child constant in parent class in java

好的,所以我有一个有趣的问题。我正在使用 java/maven/spring-boot/cassandra... 我正在尝试创建他们使用的 Mapper 设置的动态实例化。 即

//Users.java
import com.datastax.driver.mapping.annotations.Table;

@Table(keyspace="mykeyspace", name="users")
public class Users {
    @PartitionKey
    public UUID id;
    //...
}

现在,为了使用它,我必须明确地说...

Users user = (DB).mapper(Users.class);

显然用我的数据库 class 替换 (DB)。 这是一个很棒的模型,但我 运行 陷入了代码重复的问题。我的 Cassandra 数据库有 2 个键空间,两个键空间都有完全相同的表,表中的列完全相同,(这不是我的选择,根据我的公司,这是绝对必须的)。因此,当我需要根据表单提交访问一个或另一个时,它会变成一堆重复的代码,例如:

//myWebController.java
import ...;

@RestController
public class MyRestController {

@RequestMapping(value="/orders", method=RequestMethod.POST)
public string getOrders(...) {
    if(Objects.equals(client, "first_client_name") {
        //do all the things to get first keyspace objects like....
        FirstClientUsers users = (db).Mapper(FirstClientUsers.class);
        //...
    } else if(Objects.equals(client, "second_client_name") {
        SecondClientUsers users = (db).Mapper(SecondClientUsers.class);
        //....
    }
    return "";
}

我一直在尝试使用像...

这样的方法
Class cls = Class.forName(STRING_INPUT_VARIABLE_HERE);

这对基础 classes 来说工作正常,但是当尝试使用访问器时它不再工作,因为访问器必须是接口,所以当你做 Class cls 时,它不是更长的界面。

我正在尝试寻找任何其他解决方案,以了解如何动态地进行这项工作,而不必为每个可能的客户端都提供重复的代码。每个客户端在 Cassandra 中都有自己的命名空间,与所有其他客户端具有完全相同的表。

我无法更改数据库模型,这是公司必须的。 使用 PHP 这非常简单,因为它不太关心类型转换,我可以轻松地做到...

function getData($name) {
    $className = $name . 'Accessor';
    $class = new $className();
}

我有一个动态 class,但我 运行 遇到的问题是我必须明确说明的类型规范...

FirstClientUsers users = new FirstClientUsers();
//or even
FirstClientUsers users = Class.forName("FirstClientUsers");

我希望这是有道理的,我无法想象我是第一个遇到这个问题的人,但我在网上找不到任何解决方案。所以我真的希望有人知道我如何在不为我们拥有的每个键空间复制完全相同的逻辑的情况下完成这项工作。它使代码不可维护且不必要地长。

提前感谢您提供的任何帮助。

不要在模型中指定键空间 classes,而是使用所谓的 "session per keyspace" 模式。

你的模型 class 看起来像这样(注意键空间未定义):

@Table(name = "users")
public class Users {
    @PartitionKey
    public UUID id;
    //...
}

你的初始化代码应该是这样的:

Map<String, Mapper<Users>> mappers = new ConcurrentHashMap<String, Mapper<Users>>();

Cluster cluster = ...;

Session firstClientSession = cluster.connect("keyspace_first_client");
Session secondClientSession = cluster.connect("keyspace_second_client");

MappingManager firstClientManager = new MappingManager(firstClientSession);
MappingManager secondClientManager = new MappingManager(secondClientSession);

mappers.put("first_client", firstClientManager.mapper(Users.class));
mappers.put("second_client", secondClientManager.mapper(Users.class));

// etc. for all clients

然后您将存储 mappers 对象,并通过依赖项注入将其提供给应用程序中的其他组件。

最后,您的 REST 服务将如下所示:

import ...

@RestController
public class MyRestController {

    @javax.inject.Inject
    private Map<String, Mapper<Users>> mappers;

    @RequestMapping(value = "/orders", method = RequestMethod.POST)
    public string getOrders(...) {
        Mapper<Users> usersMapper = getUsersMapperForClient(client);
        // process the request with the right client's mapper
    }

    private Mapper<Users> getUsersMapperForClient(String client) {
        if (mappers.containsKey(client))
            return mappers.get(client);
        throw new RuntimeException("Unknown client: " + client);
    }
}

注意 mappers 对象是如何注入的。

小尼特:我会用单数命名你的class User而不是Users(复数)。