Mybatis Many-to-One Association Mapping Techniques

Mybatis Many-to-One Association Mapping Techniques

Database Schema Setup

First, let's create the database tables for our example. We'll have two tables: one for nations and another for leaders.


CREATE DATABASE `demo_db` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

CREATE TABLE `demo_db`.`nation` (
  `nation_id` INT(10) NOT NULL AUTO_INCREMENT,
  `nation_name` VARCHAR(20) NOT NULL,
  PRIMARY KEY(`nation_id`)
) ENGINE = InnoDB;

CREATE TABLE `demo_db`.`leader` (
  `leader_id` INT(10) NOT NULL AUTO_INCREMENT,
  `leader_name` VARCHAR(20) NOT NULL,
  `nation_id` INT(10) NOT NULL,
  PRIMARY KEY(`leader_id`)
) ENGINE = InnoDB;

INSERT INTO `nation` (`nation_id`, `nation_name`) VALUES ('1', 'United States');
INSERT INTO `nation` (`nation_id`, `nation_name`) VALUES ('2', 'United Kingdom');

INSERT INTO `leader` (`leader_id`, `leader_name`, `nation_id`) VALUES ('1', 'John Smith', '1');
INSERT INTO `leader` (`leader_id`, `leader_name`, `nation_id`) VALUES ('2', 'Mike Johnson', '1');
INSERT INTO `leader` (`leader_id`, `leader_name`, `nation_id`) VALUES ('3', 'Robert Brown', '2');
INSERT INTO `leader` (`leader_id`, `leader_name`, `nation_id`) VALUES ('4', 'David Wilson', '2');
INSERT INTO `leader` (`leader_id`, `leader_name`, `nation_id`) VALUES ('5', 'James Taylor', '2');

Entity Classes

Let's define the entity classes for our database tables.


public class Nation {
    private Integer nationId;
    private String nationName;

    public Integer getNationId() {
        return nationId;
    }

    public void setNationId(Integer nationId) {
        this.nationId = nationId;
    }

    public String getNationName() {
        return nationName;
    }

    public void setNationName(String nationName) {
        this.nationName = nationName;
    }

    @Override
    public String toString() {
        return "Nation{" +
                "nationId=" + nationId +
                ", nationName='" + nationName + '\'' +
                '}';
    }
}


public class Leader {
    private Integer leaderId;
    private String leaderName;
    private Nation nation;

    public Integer getLeaderId() {
        return leaderId;
    }

    public void setLeaderId(Integer leaderId) {
        this.leaderId = leaderId;
    }

    public String getLeaderName() {
        return leaderName;
    }

    public void setLeaderName(String leaderName) {
        this.leaderName = leaderName;
    }

    public Nation getNation() {
        return nation;
    }

    public void setNation(Nation nation) {
        this.nation = nation;
    }

    @Override
    public String toString() {
        return "Leader{" +
                "leaderId=" + leaderId +
                ", leaderName='" + leaderName + '\'' +
                ", nation=" + nation +
                '}';
    }
}

MyBatis Utility Class

Here's a utility class to create SqlSession instances:


public class MyBatisUtil {
    private static SqlSessionFactory sqlSessionFactory;

    public static SqlSession getSqlSession() {
        try {
            if (sqlSessionFactory == null) {
                InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            }
            return sqlSessionFactory.openSession();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

Mapper Interface

Define the interface for database operations:


public interface LeaderMapper {
    Leader selectLeaderById(int leaderId);
    Leader selectLeaderByIdWithJoin(int leaderId);
}

Mapper Configuration

Now, let's configure the mapper XML file with two approaches for many-to-one association mapping:




<mapper namespace="mapper.LeaderMapper">
    
    
    <select id="selectNationById" resultType="Nation">
        SELECT * FROM nation WHERE nation_id = #{nationId}
    </select>
    
    <resultMap id="leaderResultMap" type="Leader">
        <id column="leader_id" property="leaderId"/>
        <result column="leader_name" property="leaderName"/>
        <association property="nation" 
                     javaType="Nation"
                     select="selectNationById"
                     column="nation_id"/>
    </resultMap>
    
    <select id="selectLeaderById" resultMap="leaderResultMap">
        SELECT leader_id, leader_name, nation_id
        FROM leader
        WHERE leader_id = #{leaderId}
    </select>

    
    <select id="selectLeaderByIdWithJoin" resultMap="leaderResultMapWithJoin">
        SELECT l.leader_id, l.leader_name, l.nation_id, 
               n.nation_id, n.nation_name
        FROM leader l
        JOIN nation n ON l.nation_id = n.nation_id
        WHERE l.leader_id = #{leaderId}
    </select>
    
    <resultMap id="leaderResultMapWithJoin" type="Leader">
        <id column="leader_id" property="leaderId"/>
        <result column="leader_name" property="leaderName"/>
        <association property="nation" javaType="Nation">
            <id property="nationId" column="nation_id"/>
            <result property="nationName" column="nation_name"/>
        </association>
    </resultMap>
    
</mapper>

Unit Testing

Let's write unit tests to verify our implementation:


public class LeaderMapperTest {
    private LeaderMapper leaderMapper;
    private SqlSession sqlSession;
    
    @Before
    public void setUp() {
        sqlSession = MyBatisUtil.getSqlSession();
        leaderMapper = sqlSession.getMapper(LeaderMapper.class);
    }
    
    @Test
    public void testSelectLeaderById() {
        Leader leader = leaderMapper.selectLeaderById(1);
        System.out.println(leader);
    }
    
    @Test
    public void testSelectLeaderByIdWithJoin() {
        Leader leader = leaderMapper.selectLeaderByIdWithJoin(1);
        System.out.println(leader);
    }
    
    @After
    public void tearDown() {
        if (sqlSession != null) {
            sqlSession.close();
        }
    }
}

Sample Output

When running the tests, you should see output similar to this:


[main] DEBUG mapper.LeaderMapper.selectLeaderByIdWithJoin - ==>  Preparing: SELECT l.leader_id, l.leader_name, l.nation_id, n.nation_id, n.nation_name FROM leader l JOIN nation n ON l.nation_id = n.nation_id WHERE l.leader_id = ? 
[main] DEBUG mapper.LeaderMapper.selectLeaderByIdWithJoin - ==> Parameters: 1(Integer)
[main] DEBUG mapper.LeaderMapper.selectLeaderByIdWithJoin - <==      Total: 1
Leader{leaderId=1, leaderName='John Smith', nation=Nation{nationId=1, nationName='United States'}}

Tags: MyBatis java database ORM Association Mapping

Posted on Wed, 23 Sep 2026 16:34:10 +0000 by php_beginner_83