在hibernate中可以进行一对一,多对一,一对多,多对多,MyBatis中也可以实现这种映射,但是映射就显得比较麻烦了,下面看一个一对一的例子,学了hibernate都知道其实一对一跟一对多的原理其实是一致的,所以也是一对多的例子:
首先配置SqlMapConfig.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- 配置管理器 -->
<configuration>
<!-- 别名 -->
<typeAliases>
<typeAlias type="org.leadfar.Person" alias="Person"/>
<typeAlias type="org.leadfar.IdCard" alias="IdCard"/>
</typeAliases>
<!-- 配置数据库连接信息 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>
<!-- 映射文件定位 -->
<mappers>
<mapper resource="org/leadfar/PersonMapper.xml" />
<mapper resource="org/leadfar/IdCardMapper.xml" />
</mappers>
</configuration>
然后是PersonMapper.xml,IdCardMapper.xml
<?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="org.leadfar.Person">
<!-- 设置keyProperty 跟useGeneratedKeys可以获取自增长的ID 只支持具有自增长方式的那种数据库,如,mysql,sql server(oracle不支持)-->
<insert id="insert" parameterType="Person" keyProperty="id" useGeneratedKeys="true">
insert into t_person(id,t_name,age,birthday) values(#{id},#{name},#{age},#{birthday})
</insert>
<!-- 当实体类属性跟数据库字段不一致时映射结果集 -->
<resultMap type="Person" id="result_person">
<result property="name" column="t_name"/>
</resultMap>
<select id="selectOne" parameterType="int" resultMap="result_person">
select * from t_person where id=#{id}
</select>
</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="org.leadfar.IdCard">
<!-- 设置keyProperty 跟useGeneratedKeys可以获取自增长的ID 只支持具有自增长方式的那种数据库,如,mysql,sql server(oracle不支持)-->
<insert id="insert" parameterType="Person" keyProperty="id" useGeneratedKeys="true">
insert into t_idcard(number,person_id) values(#{idCard.number},#{id})
</insert>
<!-- 通过关联对象ID另外发出一条SQL语句来查询关联对象,
这样的查询如果查询对象是一个集合的话会出现N+1问题,
通过一条SQL语句查询对象列表即1,再通过每条记录关联的对象Id查询关联对象即N
<resultMap type="IdCard" id="idCardMap">
<association property="person" column="person_id" javaType="Person" select="org.leadfar.Person.selectOne"/>
</resultMap>
<select id="selectIdCard" parameterType="int" resultMap="idCardMap">
select * from t_IdCard where id=#{id}
</select>
-->
<!—下面通过连接查询可以解决N+1问题
--!>
<resultMap type="IdCard" id="idCardMap">
<id property="id" column="i_id"/>
<result property="number" column="i_number"/>
<association property="person" column="person_id" javaType="Person" resultMap="personMap"/>
</resultMap>
<resultMap type="Person" id="personMap">
<id property="id" column="p_id"/>
<result property="name" column="p_name"/>
<result property="age" column="p_age"/>
<result property="birthday" column="p_birthday"/>
</resultMap>
<select id="selectIdCard" parameterType="int" resultMap="idCardMap">
select
i.id as i_id,
i.number as i_number,
p.id as p_id,
p.t_name as p_name,
p.age as p_age,
p.birthday as p_birthday
from
t_IdCard i left outer join t_person p on i.person_id = p.id
where i.id=#{id}
</select>
</mapper>
分别测试N+1的那个映射,和不会出现N+1的映射:
private SqlSessionFactory factory;
public TestAssociation(){
//读取主配置文件的读取器
try {
Reader reader =Resources.getResourceAsReader("SqlMapConfig.xml");
System.out.println("fuq"+reader);
//基于reader通过SqlSessionFactoryBuilder构建工厂
factory=new SqlSessionFactoryBuilder().build(reader);
System.out.println("factory"+factory);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void testFindById() {
//通过factory获得数据库连接会话
SqlSession session=factory.openSession();
try{
IdCard idCard = (IdCard)session.selectOne(IdCard.class.getName()+".selectIdCard",3);
System.out.println("IdCard====="+idCard.getNumber());
System.out.println("Name====="+idCard.getPerson().getName());
session.commit();
}catch(Exception e){
session.rollback();
e.printStackTrace();
}finally{
session.close();
}
}
public void testFindById2() {
//通过factory获得数据库连接会话
SqlSession session=factory.openSession();
try{
IdCard idCard = (IdCard)session.selectOne(IdCard.class.getName()+".selectIdCard",3);
System.out.println("IdCard====="+idCard.getNumber());
System.out.println("Name====="+idCard.getPerson().getName());
session.commit();
}catch(Exception e){
session.rollback();
e.printStackTrace();
}finally{
session.close();
}
}