首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用java.util.Collections来模拟SQL内部联接操作?

如何使用java.util.Collections来模拟SQL内部联接操作?
EN

Stack Overflow用户
提问于 2018-12-03 16:51:11
回答 3查看 1.2K关注 0票数 3

如何使用Java集合来模拟SQL内部联接操作?

在数据库中,我有:

餐桌人

代码语言:javascript
复制
KEY  NAME
11   Senor
other non-important entries...

桌上的东西

代码语言:javascript
复制
KEY  ITEM
AA   Moustache
BB   Sombrero
CC   HotSauce
other non-important entries...

表PersonToThing

代码语言:javascript
复制
PERSON_KEY  THING_KEY  HAS
11          AA         Y
11          BB         N
11          CC         Y
other non-important entries...

我想模仿SQL语句:

代码语言:javascript
复制
SELECT Person.NAME, Thing.ITEM, PersonToThing.HAS 
FROM Person 
INNER JOIN PersonToThing ON Person.KEY=PersonToThing.PERSON_PKEY
INNER JOIN Thing ON Thing.KEY=PersonToThing.THING_KEY
WHERE Person.NAME="Senor";

它产生结果集:

代码语言:javascript
复制
NAME   ITEM       HAS
Senor  Moustache  Y
Senor  Sombrero   N
Senor  HotSauce   Y

我想把每个表放在一个Java中。

我已经将表导出到INSERT TABLE语句中。

我将通过遍历INSERT TABLE语句来填充Maps。

不幸的是,运行关系数据库建模系统是不可能的。

我不明白的是如何组织集合或地图,以及如何将它们链接在一起以模拟内部连接操作?

提前感谢您的时间和您所能给予的任何帮助。

EN

回答 3

Stack Overflow用户

发布于 2018-12-03 17:41:37

在你的例子中,人和事物之间有一对多的关系。对我来说,从数据库的角度来考虑这种关系要比从Java/OOP的角度考虑这种关系要困难得多。

在DB中,将person表连接到thing表,以提供每个人拥有的东西的列表。

这可以作为一张东西的地图进入你的应用程序,每一张都有拥有每一件东西的人的列表,或者作为一张人的地图,每一张都有他们拥有的东西的列表。

所以,在Java中,您本质上是在询问如何对其建模:

代码语言:javascript
复制
public class Person() {    
   private List<Thing> things;
}

...

public class SomeClass() {
    private List<Person> peopleWithThings;
}  

海事组织,你可以用两种方法-

  1. 只需像我前面所做的那样,在您的域中使用普通的旧Java对象。
  2. 使用像番石榴的multimap这样的东西来创建一个字符串映射(人名)到一个事物列表。

使用multimap,您可以得到如下内容:

代码语言:javascript
复制
String key = "Senor";
Multimap<String, Thing> map = ArrayListMultimap.create();

map.put(key, thing1);
map.put(key, thing2);

assertEquals(2, map.size());
票数 1
EN

Stack Overflow用户

发布于 2018-12-03 17:51:57

在集合论中,内连接本质上是一个操作。Java集合没有内置的完全相同的集合论函数,但是对于联合(addAll)和交集(retainAll),它们确实有类似的函数。有关如何使用Set或其他集合实现内部连接/交叉的更多详细信息,请参见这个问题

使用集合论的主要挑战是存在三种不同的对象类型,没有一种是相互继承的,在适当的关系模型中可能会出现这种情况。例如,如果Person和Thing都继承自PersonToThing作为父类,那么它将大大简化事情:

代码语言:javascript
复制
class Person extends PersonToThing {
    // ...
}

class Thing extends PersonToThing {
    // ...
}

class PersonToThing {
    // now Person_Key and Thing_Key can be inherited
    String personKey;
    String thingKey;
    // etc...
}

使用这个模型,我们现在可以拥有一个PersonToThing对象的集合,并正确地说明一对多的关系:

代码语言:javascript
复制
Set<PersonToThing> people = selectAllFrom("Person");
Set<PersonToThing> thing = selectAllFrom("Thing");
Set<PersonToThing> innerJoin = people;
people.addAll(thing);
innerJoin.retainAll(thing);

如果您重写对象的equals()函数来检查您的密钥,您可以执行任何您喜欢的连接,包括Senor过滤器,或者添加一个实用程序函数,使它成为一个更可重用和更友好的设计:

代码语言:javascript
复制
@Override
public boolean equals(Object personToThing) {
    if (personToThing.getPersonKey() != null) {
        return personKey.equals(personToThing.getPersonKey());
    else
        return thingKey.equals(personToThing.getThingKey());
}

这是因为Set使用equals()来检查两个对象是否相同。这样,当它这样做时,我们就像连接一样比较键。

我保留了selectAllFrom()函数抽象的细节,因为您没有提供任何特定于数据库的样板代码,但是无论您需要怎样实现它都应该相当简单。

票数 0
EN

Stack Overflow用户

发布于 2018-12-03 18:54:05

嗯,这似乎不容易,但这是可能的。

首先进行一些准备--为了使用简单的注释生成getter/setter和构造函数,我使用Lombok项目,只需创建一个Maven项目并将这个依赖项添加到其中:

代码语言:javascript
复制
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.4</version>
    <scope>provided</scope>
</dependency>

下面是具有数据的类和表的定义:

代码语言:javascript
复制
@AllArgsConstructor @Getter
public static class Person {
    private String key, name;
}

@AllArgsConstructor @Getter
public static class Thing {
    private String key, item;
}

@AllArgsConstructor @Getter
public static class PersonToThing {
    private String personKey, thingKey, has;
}

static Collection<Person> tablePerson = Arrays.asList(
        new Person("11", "Senor"),
        new Person("22", "Tom"));

static Collection<Thing> tableThing = Arrays.asList(
        new Thing("AA", "Moustache"),
        new Thing("BB", "Sombrero"),
        new Thing("CC", "HotSauce"),
        new Thing("XX", "Not important")
);

static Collection<PersonToThing> tablePerson2Thing = Arrays.asList(
        new PersonToThing("11", "AA","Y"),
        new PersonToThing("11", "BB","N"),
        new PersonToThing("11", "CC","Y"));

现在,对这三个集合执行连接的一段代码。

代码语言:javascript
复制
@AllArgsConstructor(staticName = "of") @Getter
public static class Tuple<V1,V2>{
    private V1 v1;
    private V2 v2;
}

@AllArgsConstructor(staticName = "of") @Getter
public static class Triple<V1,V2,V3>{
    private V1 v1;
    private V2 v2;
    private V3 v3;
}

public static void main(String[] args) {
    tablePerson.stream()
            // WHERE Person.NAME="Senor";
            .filter(x->x.getName()=="Senor")
            // INNER JOIN PersonToThing
            .flatMap( p -> tablePerson2Thing.stream()
                    .map(p2t-> Tuple.of(p,p2t))
                    // ON Person.KEY=PersonToThing.PERSON_PKEY
                    .filter(t->t.getV1().getKey()==t.getV2().getPersonKey())
            )
            // INNER JOIN Thing
            .flatMap( p2t-> tableThing.stream()
                    .map(t-> Triple.of(p2t.getV1(),p2t.getV2(),t))
                    // ON Thing.KEY=PersonToThing.THING_KEY
                    .filter(t->t.getV2().getThingKey()==t.getV3().getKey())
            )
            // SELECT Person.NAME, Thing.ITEM, PersonToThing.HAS 
            .forEach(x->System.out.println(x.getV1().getName()+ " / " + x.getV3().getItem() + " /  " + x.getV2().getHas()));
}

其结果是:

代码语言:javascript
复制
Senor / Moustache /  Y
Senor / Sombrero /  N
Senor / HotSauce /  Y
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53598249

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档