1

我有一个名称列表:List<Name>Name有两种方法:

  • toString()返回“姓名:汤姆”
  • getName()返回“汤姆”

要查询具有某些姓名的人的数据库,我会这样做

// Query a single database entry
Query query = em.createQuery("FROM person WHERE name = :name");
query.setParameter("name", names.get(0).getName());

当我想查询多个条目时(使用WHERE ... IN (...)我必须这样做:

// Convert the list of name instances to a list of strings
List<String> nameStrings = new ArrayList<String>(names.size());
for (Name name : names) {
  nameStrings.add(name.getName());
}

// Query multiple database entries
Query query = em.createQuery("FROM person WHERE name in (:name)");
query.setParameter("name", nameStrings); // JPA
query.setParameterList("name", nameStrings); // Hibernate

我必须建立第二个列表吗?我宁愿这样做:

// Query a single database entry
Query query = em.createQuery("FROM person WHERE name = :name");
query.setParameter("name", names.get(0));

// Query for multiple database entries
Query query = em.createQuery("FROM person WHERE name in (:name)");
query.setParameter("name", names); // JPA
query.setParameterList("name", names); // Hibernate
4

1 回答 1

1

简短的回答是肯定的,您需要构建第二个列表。您需要提供 a Listof Strings (或者更确切地说是 a Collection), aList<Name>永远不会匹配这个。我建议制作某种实用方法,该方法采用 aList<Name>并返回 aList<String>名称。

public static List<String> toNameStrings(List<Name> names) {
    List<String> list = new ArrayList<String>(names.size());
    for (Name name : names) {
        list.add(name.getName());
    }
    return list;
}

我无法测试以下内容,并且我不确定是否要以任何方式推荐它,但我认为您可以创建一个List实现,根据它所处的状态返回不同的对象类型。使用这个你' 将能够做一些事情,比如list.setStringMode(false)将它用作 a List<Name>(尽管在这个阶段泛型正在退出窗口,它们都将返回为Object),然后list.setStringMode(true),将它用作List<String>. 它看起来像下面这样:

public class NameAndStringList extends ArrayList<Object> implements List<Object>
{
    private boolean stringMode = false;

    @Override
    public boolean add(Object object)
    {
        return super.add(toName(object));
    }

    // Do the same for add(index, element)
    // Do the same for set(index, element)
    // Do the same for remove(object)

    @Override
    public boolean addAll(Collection<? extends Object> collection)
    {
        final List<Name> convertedCollection = new ArrayList<Name>();
        for (Object object : collection)
        {
            convertedCollection.add(toName(object));
        }
        return super.addAll(convertedCollection);
    }

    // Do the same for addAll(index, collection)
    // Do the same for removeAll(index, collection)
    // Do the same for retainAll(index, collection)

    @Override
    public boolean contains(Object o)
    {
        return super.contains(toName(o));
    }

    // Do the same for containsAll(collection)
    // Do the same for indexOf(object)
    // Implement Iterator that checks the stringMode variable before returning value.
    // Override all iterator methods to retrieve custom Iterator implementation.
    // Override subList(fromIndex, toIndex) to make subList be an instance of NameAndStringList as well.

    @Override
    public Object get(int index)
    {
        if (stringMode)
        {
            return ((Name) super.get(index)).getName();
        }
        return super.get(index);
    }

    // Implement setStringMode(boolean)

    protected Object toNameString(Object object)
    {
        if (object instanceof Name)
        {
            // Convert to String here
        }
        return object;
    }

    protected Name toName(Object object)
    {
        if (object instanceof String)
        {
            // Convert to Name here.
        }
        return object;
    }
}

请注意,这依赖于您能够将 a 转换String为 aName以及反之亦然,但如果您知道始终使用Name实例自己填充它,则始终可以摆脱该位。这里的一般想法是List存储Name实例,但可以自由返回String实例,因为它是一个List<Object>. 同样,我不确定我是否会推荐这种方法,但它应该满足您的要求,或者至少尽可能接近 atm。

于 2012-08-22T09:01:10.943 回答