一、properties属性

使用Properteis加载一个资源文件,资源文件中可以配置各种属性。
我们添加一个db.properties

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mis
username=root
password=root

在MyBatis的配置文件中引用这个文件

  1. <!-- 使用propertiees引用外部的资源文件 -->
  2. <properties resource="db.properties">
  3. <!-- 自定义属性 -->
  4. <property name="username" value="admin"/>
  5. <property name="maxsize" value="18"/>
  6. </properties>

有了这个引用后,可以在dataSource中使用属性值:

<environments default="development">
  <environment id="development">
    <!-- 事务管理 -->
    <transactionManager type="JDBC"/> 
    <dataSource type="POOLED"> 
      <!-- 无需多说 -->
      <property name="driver" value="${driver}"/> 
      <property name="url" value="${url}"/> 
      <property name="username" value="${username}"/>
      <property name="password" value="${password}"/>
      <!-- 使用当前文件中定义的属性 --> 
          <property name="maxsize" value="${maxsize}"/> 
    </dataSource>
  </environment>
</environments>

注:如果在外部的properties中配置的属性和当前的配置文件的标签下的属性重复,则外
部的属性值会覆盖当前配置文件中的属性值。

二、类型别名(typeAliases)☆☆☆

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例
如:

<typeAliases> 
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
  <typeAlias alias="Comment" type="domain.blog.Comment"/>
  <typeAlias alias="Post" type="domain.blog.Post"/>
  <typeAlias alias="Section" type="domain.blog.Section"/>
  <typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>

也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

每一个在包 domain.blog 中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限
定类名来作为它的别名。 比如 domain.blog.Author 的别名为 author ;若有注解,则别名为其注解
值。见下面的例子:

@Alias("author")
public class Author { ... }
<!-- 别名 --> 
<typeAliases>
  <!-- 配置一个别名 --> 
  <typeAlias type="com.st.pojo.Teacher" alias="teacher"/> 
  <!-- 配置一个包,这个包下的所有的类都可以直接使用类的简称(不区分首字母大小写) -->
  <package name="com.st.pojo"/> <!-- teacher / Teacher -->
</typeAliases>

插件(plugins)-知道

MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来
拦截的方法调用包括:

Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) ParameterHandler (getParameterObject, setParameters) ResultSetHandler (handleResultSets, handleOutputParameters) StatementHandler (prepare, parameterize, batch, update, query)

这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看 MyBatis 发行包中的源代码。
如果你想做的不仅仅是监控方法的调用,那么你最好相当了解要重写的方法的行为。 因为在试图修改或
重写已有方法的行为时,很可能会破坏 MyBatis 的核心模块。 这些都是更底层的类和方法,所以使用
插件的时候要特别当心。
通过 MyBatis 提供的强大机制,使用插件是非常简单的,只需实现 Interceptor 接口,并指定想要拦截
的方法签名即可。
**

环境配置(environments)

MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中, 现实情况下
有多种理由需要这么做。例如,开发、测试和生产环境需要有不同的配置;或者想在具有相同 Schema
的多个生产数据库中使用相同的 SQL 映射。还有许多类似的使用场景。
不过要记住:尽管可以配置多个环境,但每个** SqlSessionFactory **实例只能选择一种环境。
**

映射器(mappers)☆☆☆☆☆

既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们
需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方
案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引
用,或完全限定资源定位符(包括 file:/// 形式的 URL),或类名和包名等。例如:

<!-- 使用相对于类路径(classpath)的资源引用 -->
<mappers>
  <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  <mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
<!-- 使用完全限定资源定位符(URL) -->
<mappers>
  <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  <mapper url="file:///var/mappers/BlogMapper.xml"/>
  <mapper url="file:///var/mappers/PostMapper.xml"/>
</mappers>
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
  <mapper class="org.mybatis.builder.AuthorMapper"/>
  <mapper class="org.mybatis.builder.BlogMapper"/>
  <mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
  <!-- 最常用的方式 -->
  <package name="org.mybatis.builder"/>
</mappers>

关联映射

关系类型:

一对一 一对多 多对多 多对一

MyBatis的关联关系:
第一种:持有对方一个引用(学生对班级)
第二种:持有对方一组引用(班级对学生)

关联映射配置

一对一映射:连接查询

学生持有班级的一个引用:
第一种配置方式(使用连接查询):

<!-- 结果映射 -->
<!-- 映射数据表和类的属性之间的关系 -->
<resultMap id="studentMapping" type="com.st.pojo.Student">
    <!-- 每一张表都有主键,先要映射主键 -->
    <!-- column:列名    property:属性名   JavaType:类型(一般都是自动识别) -->
    <id column="stuId" property="stuId" javaType="java.lang.Long"/>
    <!-- 映射其他属性 -->
    <result column="stuName" property="studentName" jdbcType="VARCHAR"/>
    <result column="longinPass" property="loginPass" />
    <result column="stuGender" property="stuGender"/>
    <result column="stuAge" property="stuAge"/>
    <result column="stuBirth" property="stuBirth"/>
    <result column="stuTel" property="stuTel"/>
    <result column="stuEducation" property="stuEducation"/>
    <result column="status" property="status"/>
    <result column="classId" property="classId"/>

    <!-- 一对一的关联映射 -->
    <association property="classInfo" javaType="com.st.pojo.ClassInfo" column="classId">
        <!-- 配置班级的映射信息 -->
        <id column="classId" property="classId"/>
        <result property="className" column="className"/>
        <result property="roomId" column="roomId"/>
        <result property="teacherId" column="teacherId"/>
        <result property="headmasterId" column="headmasterId"/>
        <result property="startTime" column="startTime"/>
        <result property="endTime" column="endTime"/>
        <result property="status" column="status"/>
    </association>
</resultMap>

这个配置方式,在查询的时候,必须使用连接查询:

<!-- 关联映射使用连接查询 -->
<select id="queryStuById" parameterType="long" resultMap="studentMapping">
    select st.*,c.className,c.roomId,c.teacherId,c.headmasterId,c.startTime,c.endTime,c.status
    from student st join classinfo c on st.classid = c.classid
    where st.stuId = #{stuId}
</select>

测试

@Test
public void testAnnotationSql(){
    SqlSession sqlSession = factory.openSession();
    Student st = sqlSession.selectOne("com.st.mapper.StudentMapper.queryStuById",1L);
    System.out.println(st);
    System.out.println(st.getClassInfo());
}

**


一对一映射:子查询

<!-- 关联映射-子查询 -->
<!-- 结果映射 -->
<!-- 映射数据表和类的属性之间的关系 -->
<resultMap id="stuResMapping" type="com.st.pojo.Student">
    <!-- 每一张表都有主键,先要映射主键 -->
    <!-- column:列名    property:属性名   JavaType:类型(一般都是自动识别) -->
    <id column="stuId" property="stuId" javaType="java.lang.Long"/>
    <!-- 映射其他属性 -->
    <result column="stuName" property="studentName" jdbcType="VARCHAR"/>
    <result column="longinPass" property="loginPass" />
    <result column="stuGender" property="stuGender"/>
    <result column="stuAge" property="stuAge"/>
    <result column="stuBirth" property="stuBirth"/>
    <result column="stuTel" property="stuTel"/>
    <result column="stuEducation" property="stuEducation"/>
    <result column="status" property="status"/>
    <result column="classId" property="classId"/>
    <!-- 一对一的关联映射 子查询 -->
    <association property="classInfo" javaType="com.st.pojo.ClassInfo" column="classId" 
                 select="querClassById"/>
</resultMap>
<!-- 根据班级编号查询班级 --><!-- 应该配置在班级的映射文件中,我们纯粹是为了方便演示 -->
<select id="querClassById" parameterType="long" resultType="classInfo">
    select * from classInfo where classId=#{cid}
</select>
<!-- 根据id查询学生 -->
<select id="queryByStudentId" parameterType="long" resultMap="stuResMapping">
    select * from student where stuId=#{stuId}
</select>

测试

@Test
public void testOne2One_2(){
    SqlSession sqlSession = factory.openSession();
    Student st = sqlSession.selectOne("com.st.mapper.StudentMapper.queryByStudentId",1L);
    System.out.println(st);
    System.out.println(st.getClassInfo());
}


一对多关联映射:连接查询

第一种方式:连接查询
在班级的对象中有一组学生对象

select st.stuId,st.stuName as studentName,st.longinPass as loginPass,
st.stuGender,st.stuAge,st.stuBirth,st.stuTel,st.stuEducation,
c.classid,c.className,c.roomId,c.teacherId,c.headmasterId,c.startTime,c.endTime,c.status
from student st join classinfo c on st.classid = c.classid
where st.stuId = 1
<!-- 一对多的关联映射 -->
<resultMap id="classAndStudentResMapping" type="classInfo">
    <!-- 配置班级的映射信息 -->
    <id column="classId" property="classId"/>
    <result property="className" column="className"/>
    <result property="roomId" column="roomId"/>
    <result property="teacherId" column="teacherId"/>
    <result property="headmasterId" column="headmasterId"/>
    <result property="startTime" column="startTime"/>
    <result property="endTime" column="endTime"/>
    <result property="status" column="status"/>
    <!-- 配置一对多的关联映射 -->
    <!-- property:属性名  javaType:集合类型  ofType:集合中的类型 -->
    <collection property="students" javaType="java.util.List" ofType="student" column="classId">
        <!-- student的映射关系 -->
        <!-- column:列名    property:属性名   JavaType:类型(一般都是自动识别) -->
        <id column="stuId" property="stuId" javaType="java.lang.Long"/>
        <!-- 映射其他属性 -->
        <result column="stuName" property="studentName" jdbcType="VARCHAR"/>
        <result column="longinPass" property="loginPass" />
        <result column="stuGender" property="stuGender"/>
        <result column="stuAge" property="stuAge"/>
        <result column="stuBirth" property="stuBirth"/>
        <result column="stuTel" property="stuTel"/>
        <result column="stuEducation" property="stuEducation"/>
        <result column="status" property="status"/>
        <result column="classId" property="classId"/>
    </collection>
</resultMap>
<!-- 根据id查询查询班级信息,同时查询这个班级的所有学生信息 -->
<select id="queryClassAndStuByCid" parameterType="long" resultMap="classAndStudentResMapping">
    select st.stuId,st.stuName as studentName,st.longinPass as loginPass,st.stuGender,st.stuAge,st.stuBirth,st.stuTel,st.stuEducation,
    c.classid,c.className,c.roomId,c.teacherId,c.headmasterId,c.startTime,c.endTime,c.status
    from student st join classinfo c on st.classid = c.classid
    where c.classId=#{cid}
</select>
@Test
public  void testOne2Many(){
    SqlSession sqlSession = factory.openSession();
    ClassInfo classInfo = sqlSession.selectOne("com.st.mapper.ClassInfoMapper.queryClassAndStuByCid",1L);
    System.out.println(classInfo);
    for (Student st : classInfo.getStudents()){
        System.out.println(st);
    }
}

一对多关联映射:子查询

<!-- 子查询配置 -->
<!-- 一对多的关联映射 -->
<resultMap id="classAndStudentResMapping1" type="classInfo">
    <!-- 配置班级的映射信息 -->
    <id column="classId" property="classId"/>
    <result property="className" column="className"/>
    <result property="roomId" column="roomId"/>
    <result property="teacherId" column="teacherId"/>
    <result property="headmasterId" column="headmasterId"/>
    <result property="startTime" column="startTime"/>
    <result property="endTime" column="endTime"/>
    <result property="status" column="status"/>
    <!-- 配置一对多的关联映射 -->
    <!-- property:属性名  javaType:集合类型  ofType:集合中的类型 -->
    <collection property="students" javaType="java.util.List" ofType="student"
                column="classId"
    select="queryStuByCid"/>
</resultMap>
<!-- 通过班级编号查询学生列表 -->
<select id="queryStuByCid" parameterType="long" resultMap="student">
    select st.stuId,st.stuName as studentName,st.longinPass as loginPass,st.stuGender,st.stuAge,st.stuBirth,st.stuTel,st.stuEducation,st.classId
    from student st
    where st.classId=#{cid}
</select>
<!-- 通过id查询班级信息,关联映射-子查询 -->
<select id="queryClassAndStudentByCid1" parameterType="long" resultMap="classAndStudentResMapping1">
    select * from classInfo where classid=#{cid}
</select>
@Test
public  void testOne2Many2(){
    SqlSession sqlSession = factory.openSession();
    ClassInfo classInfo = sqlSession.selectOne("com.st.mapper.ClassInfoMapper.queryClassAndStudentByCid1",1L);
    System.out.println(classInfo);
    for (Student st : classInfo.getStudents()){
        System.out.println(st);
    }
}