3

Please be patient with the newbie question as I'm trying to learn MyBatis and java at the same time. I have an application in which I need to use threadsafe variables. Based on some research and my ideas of how the application will be used, I've settled on a CopyOnWriteArrayList over a Vector.

When I call a selectList from the mybatis sql session, is there any way to tell it to create an CopyOnWriteArrayList as its return rather than an ArrayList? Admittedly, my code to configure this is two lines instead of one, but something in me says that there's got to be a better way and/or I'm not the first one to have encountered this.

List<Team> teams = session.selectList("getTeamsByGameID", gameID);
List<Team> arrayListReturn = new CopyOnWriteArrayList<Team>(teams);
return arrayListReturn;

Thanks in advance,

Robert Smith
  • 385
  • 4
  • 15

1 Answers1

7

I know of two ways to handle this.

Option 1: Use a Mapper class and specify the type of List to return there.

Define a Mapper interface:

public interface TeamMapper {
  CopyOnWriteArrayList<Team> getTeamsByGameID();
}

Your mapper xml file stays the same. The code to do the query changes to:

TeamMapper m = session.getMapper(TeamMapper.class);
List<Team> lt = m.getTeamsByGameID();
System.out.println(lt.getClass());  
  //=> prints out "class java.util.concurrent.CopyOnWriteArrayList"


Option 2: Create a ResultHandler and pass that into the session.select() method.

Here you use the ResultHandler interface. That interface requires you to override one method, handleResult, which is given each result that comes back from the database as the query is in progress.

In your case, your ResultHandler would look something like this:

public class TeamResultHandler implements ResultHandler {

  private List<Team> teams = new CopyOnWriteArrayList<Team>();

  @Override
  public void handleResult(ResultContext rc) {
    countries.add((Team) rc.getResultObject());
  }

  // provide a getter so you can retrieve it when finished
  public List<Team> getTeamList() {
    return teams;
  }
}

Instead of using selectList as you do above, you would now use the session.select(String, ResultHandler), like so:

TeamResultHandler rh = new TeamResultHandler();
session.select("getTeamsByGameID", rh);
List<Team> lt = rh.getTeamList();
return lt;

This solution is more verbose than your solution (requires an extra class and three lines in your query code, rather than 2), but it only creates one List, rather than two, so you'll have to decide which fits your needs best.

In addition, ResultHandlers can be useful for additional things - making sure results are sorted in a certain way or filtered or something else, in case you need that.

quux00
  • 13,679
  • 10
  • 57
  • 69
  • Really appreciate you taking the time to throw these examples together. I'd seen the resulthandler before, but had no idea how to use one. I'm occasionally having trouble finding everything I need in the MyBatis documentation. – Robert Smith Jul 24 '12 at 14:45
  • I've found the best way to learn MyBatis is to do little examples of its various features and then keep those code snippets handy when faced with "how do I ...?" questions. The MyBatis User Guide outlines the possibilities but doesn't always show how to use each feature. To that end I created a set of "MyBatis Koans". If you don't want to do the koans, you can look at the koan content and just jump to the completed koans to see how to use certain features. Link: https://github.com/midpeter444/mybatis-koans – quux00 Jul 24 '12 at 22:22