MyBatis TooManyResultsException for seemingly correct mapping

12,796

It turns out that MyBatis doesn't understand my associations with aliased tables, so I changed my query to:

SELECT
  r.name as recipe_name,
  ri.measurement_amount as measurement_amount
FROM
  recipe r
  INNER JOIN recipe_ingredient ri on ri.recipe_id = r.id
WHERE
  r.id = #{id}

and updated the mapper to use the alias for column (recipe_name instead of ri.name, etc), as such:

<resultMap id="Recipe" type="cookbook.domain.Recipe">
    <result property="name" column="recipe_name" />
    <collection property="ingredients" ofType="cookbook.domain.RecipeIngredient">
        <result property="measurementAmount" column="measurement_amount"/>
    </collection>
</resultMap>

and it worked!

Thanks to those who commented to help

Share:
12,796
Missy Williams
Author by

Missy Williams

Updated on July 14, 2022

Comments

  • Missy Williams
    Missy Williams almost 2 years

    For the sake of resolving this problem I have pared down a lot of my code.

    I continue to get this error as I try different things to get this collection working:

    nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 2

    Relevant objects are as follows:

    class Recipe {
        String name
        List<RecipeIngredient> ingredients
    }
    class RecipeIngredient {
        Double measurementAmount
    }
    

    I have an interface with my method call:

    public interface CookbookDao {
        public Recipe getRecipe(@Param("id")int id)
    }
    

    And my result mapper:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="cookbook.daos.CookbookDao">
        <select id="getRecipe" resultMap="Recipe">
            SELECT
              r.name,
              ri.measurement_amount
            FROM
              recipe r
              INNER JOIN recipe_ingredient ri on ri.recipe_id = r.id
            WHERE
              r.id = #{id}
        </select>
    
        <resultMap id="Recipe" type="cookbook.domain.Recipe">
            <result property="name" column="r.name" />
            <collection property="ingredients" ofType="cookbook.domain.RecipeIngredient">
                <result property="measurementAmount" column="ri.measurement_amount"/>
            </collection>
        </resultMap>
    </mapper>
    

    The query returns the following results (Note: While the above code only has "measurement_amount" I've included what the actual, end-result set looks like to help show why I want/need to get these 2 rows back):

     name | measurement_amount | name | abbreviation | name  
    ------+--------------------+------+--------------+-------
     Rice |                  1 | cup  |              | rice
     Rice |                  2 | cups |              | water
    

    I can get the mapper to work when I take the collection out. I have tried using javaType and I have tried using the composite key in the collection, but it still didn't work. I have run out ideas and have looked in a ton of help posts but nothing stood out.

    I'm using Spring Boot with UTD versions of mybatis and mybatis-spring