获取Hibernate中的列表列表

时间:2014-01-13 16:32:32

标签: java hibernate

在我的项目中,我有两个实体:RaceRaceDriver,其中包含Race

class RaceDriver {

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "race", nullable = false)
    private Race race;
    ...
    @Column(name = "starting_nr")
    private Integer startingNr;
    ...
    @Column(name = "disqualified", nullable = false)
    private boolean disqualified;
}

现在,我想要的是在startingNr中获取disqualified RaceDriver的{​​{1}}列表,如下所示:

Race

问题是,现在我需要相同,但为少数 public List<Integer> findDisqualifiedDriversStartingNumbers(Integer raceId) { ProjectionList projection = Projections.projectionList() .add(Projections.property("startingNr").as("startingNr")); return getSession() .createCriteria(RaceDriver.class) .setProjection(projection) .add(Restrictions.eq("race.id", raceId)) .add(Restrictions.eq("disqualified", true)) .list(); } 。如何在不进行单独DAO调用的情况下实现此目的?因为我听说在单个数据库调用中尽可能做得更好。

我的想法是简单地获取在给定种族中被取消资格的驱动程序列表,然后在Java代码中解析它,我认为这将需要很少的循环,并制作一些不合格的Races地图的起始数字,密钥为RaceDriver

DAO尝试看起来像这样:

Race.id

问题是我会得到那些大对象,而不是我需要的唯一数据的地图或列表(public List<RaceDriver> findDisqualifiedDriversInRaces(List<Integer> raceIds) { return getSession() .createCriteria(RaceDriver.class) .add(Restrictions.in("race.id", raceIds)) .add(Restrictions.eq("disqualified", true)) .list(); } startingNr)。

所以问题是 - 我能以某种方式只使用Hibernate吗?

4 个答案:

答案 0 :(得分:2)

您需要使用具有两个WHERE条件的hibernate创建Query

@PersistenceContext protected EntityManager em;

List<Integer> raceIds = Arrays.asList(1, 2, 3);
Query query = em.createQuery("FROM RaceDriver r WHERE r.raceId IN (:raceIds) AND r.disqualified = true");
query.setParameter("raceIds", raceIds);
List<RaceDriver> drivers = query.getResultList();

这将返回您提供的raceIds中的不合格驱动程序列表。

<强>更新

获得List<RaceDriver>后,您可以循环播放drivers,并以raceId作为关键字生成HashMaps列表,并将startingNr列表(不合格的驱动程序)列为价值。

HashMap<Integer,List<Integer>> startingNrHashMap=new...;

for(RaceDriver driver:drivers)
{
  List<Integer> strNr = new ArrayList<Integer>();
  if(startingNrHashMap.containsKey(driver.race.raceid))
  {
    //if race id is already present in hash map then

    strNr = startingNrHashMap.get(driver.race.raceid);
    strNr.add(driver.startingNr);
    startingNrHashMap.put(driver.race.raceid,strNr);
  }
  else
  {
    // if race id is NOT present in hash map
    strNr.add(driver.startingNr);
    startingNrHashMap.put(driver.race.raceid,strNr);
  }
 strNr =null;
}

答案 1 :(得分:2)

我个人会在普通的java中使用这个解决方案,因为对于任何支持你的代码的开发人员来说,它会更清楚。

回答这个问题“可以通过Hibernate完成吗?”:是的,可能是ResultTransformer是正确的方式,特别是如果你的程序中需要多次进行地图转换。没有标准的变压器可以满足您的需求,但您可以编写自己的变压器:

public class MapOfListsResultTransformer<K, V> extends BasicTransformerAdapter {

    public List transformList(List collection) {
        final Map<K, List<V>> map = new HashMap<>();

        for (Object object : collection) {
            final Object[] objects = (Object[]) object;
            final K key = (K) objects[0];
            final V value = (V) objects[1];
            if (!map.containsKey(key)) {
                final List<V> list = new ArrayList<V>();
                list.add(value);
                map.put(key, list);
            } else {
                map.get(key).add(value);
            }
        }

        return Arrays.asList(map);
    }
}

它的用法如下:

public Map<Integer, List<Integer>> findDisqualifiedDriversInRaces(List<Integer> raceIds) {
    ProjectionList projection = Projections.projectionList()
            .add(Projections.property("race.id").as("race.id"))
            .add(Projections.property("startingNr").as("startingNr"));

    return (Map<Integer, List<Integer>>) getSession()
            .createCriteria(RaceDriver.class)
            .setProjection(projection)
            .add(Restrictions.in("race.id", raceIds))
            .add(Restrictions.eq("disqualified", true))
            .setResultTransformer(new MapOfListsResultTransformer<Integer, Integer>())
            .uniqueResult();
}

答案 2 :(得分:1)

我就这样做了:

DAO方法:

public List<RaceDriver> findDisqualifiedDriversInRaces(List<Integer> raceIds) {
    if (!raceIds.isEmpty()) { // it will crash if the list will have no elements!
        return getSession()
            .createCriteria(RaceDriver.class)
            .add(Restrictions.in("race.id", raceIds))
            .add(Restrictions.eq("disqualified", true))
            .list();
    }
    return Collections.emptyList();
}

然后从中提取我想要的东西,我创建了一个辅助方法:

// key = race.id, value = list of disqualified raceDrivers' starting numbers

private HashMap<Integer, List<Integer>> extractStartingNumbersToMap(List<RaceDriver> disqualifiedDrivers) {
    HashMap<Integer, List<Integer>> disqualifiedDriversMap = new HashMap<>();

    for (RaceDriver raceDriver : disqualifiedDrivers) {
        Integer raceId = raceDriver.getRace().getId();

        if (!disqualifiedDriversMap.containsKey(raceId)) {
            disqualifiedDriversMap.put(raceId, new ArrayList<>(Arrays.asList(raceDriver.getStartingNr())));
        } else {
            disqualifiedDriversMap.get(raceId).add(raceDriver.getStartingNr());
        }
    }
    return disqualifiedDriversMap;
}

我在Mark T回答之前做过,因为你可以看到它非常相似。但是我发布它,因为它可能对某人有帮助。

答案 3 :(得分:0)

我问了同样的问题,它关于NHibernate和.NET MVC,但你可以了解DAO和ResultTransformer

Question