Mybatis基于xml的开发总结

一、开发步骤

  1. 创建Mybatis主配置文件:放在resources目录下
<?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">
<!-- mybatis的住配置文件 -->
<configuration>
	<!-- 数据库连接信息的文件位置 -->
  <properties resource="db.properties"></properties>
  
  <!-- 配置信息 -->
  <settings>
    <!-- 延迟加载配置 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <setting name="aggressiveLazyLoading" value="false"/>
    <!-- 二级缓存配置 -->
    <setting name="cacheEnabled" value="true"/>
  </settings>
  
  <!-- 给包取别名 -->
  <typeAliases>
    <package name="pers.qianxian.entity"/>
  </typeAliases>
  
  <!-- 配置环境 -->
  <environments default="mysql">
    <!-- 配置mysql环境 -->
    <environment id="mysql">
      <transactionManager type="JDBC"></transactionManager>
      <dataSource type="POOLED">
        <property name="driver" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.user}"/>
        <property name="password" value="${jdbc.password}"/>
      </dataSource>
    </environment>
  </environments>

  <mappers>
    <!-- 配置文件所在位置 -->
    <!-- 方式一:使用xml配置的方式 -->
<!--    <mapper resource="pers/qianxian/dao/StudentDao.xml" />-->
	<!-- 方式二:使用注解配置的方式 -->
<!--    <mapper class="pers.qianxian.dao.StudentDao" />-->
	<!-- 适用于xml和注解的开发方式 -->
    <package name="pers.qianxian.dao"/>
  </mappers>

</configuration>
  1. 创建对应实体类的dao层接口:
public interface StudentDao {
    List<Student> findAll();
    Student findOne(String sid);
    List<Student> findInList(QueryVo vo);
    void insert(Student student);
    void update(Student student);
    void delete(String sid);
}
  1. 创建对应dao接口的mapper映射:(注意:映射文件放在resources文件夹,mapper映射文件需要和dao层接口所在包路径相同)
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace指定dao层接口的位置 -->
<!-- id表示接口的方法 -->
<mapper namespace="pers.qianxian.dao.StudentDao">
  <!-- 定义一条sql语句,可以用include标签引用 -->
  <sql id="defaultSelect">
    select * from students
  </sql>

  <!-- select标签必须指定resultType或者resultMap -->
  <select id="findAll" resultType="pers.qianxian.entity.Student">
    select * from students
  </select>

  <select id="findInList" resultType="student"
          parameterType="pers.qianxian.domain.QueryVo">
    <include refid="defaultSelect" />
    <!-- 动态sql部分 -->
    <where>
      <if test="ids != null and ids.size > 0">
        <foreach collection="ids" open="and sid in (" close=")" item="id"
                 separator=",">
          #{id}
        </foreach>
      </if>
    </where>
  </select>

  <insert id="insert" parameterType="pers.qianxian.entity.Student">
         insert into students(sid,sname,tel,email)
         values(#{sid},#{sname},#{tel}, #{email})
  </insert>

  <update id="update" parameterType="pers.qianxian.entity.Student">
        update students set sname=#{sname},tel=#{tel},email=#{email} where
        sid=#{sid}
  </update>

  <delete id="delete" parameterType="string">
    delete from students where sid=#{sid}
  </delete>
</mapper>
  1. 测试dao层
public class Test {
    public static void main(String[] args) throws IOException {
        //1、读取主配置文件
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2、创建SqlSessionFactory
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        //3、创建SqlSession对象
        SqlSession sqlSession = factory.openSession();
        	// 也可以传入true参数,表示自动提交
        	// SqlSession sqlSession = factory.openSession(true);
        //4、使用SqlSession创建Dao接口的代理对象
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //5、使用代理对象执行方法
		List<Student> students = dao.findAll();
        //6、关闭资源
        sqlSession.commit();
        sqlSession.close();
        in.close();
    }
}

二、properties标签

加载properties文件,然后可以用${键名}取到值:

	<!-- properties文件位置 -->
  <properties resource="db.properties"></properties>

三、一对一关联映射

一个学院有多个专业,一个专业只属于一个学院(在专业的mapper映射文件配置)

/**
* 学院实体类
*/
public class Academy {
    private String aid;
    private String aname;
    private String tel;
    private Set<Major> majors;

    @Override
    public String toString() {
        return "Academy{" + "aid='" + aid + '\'' + ", aname='" + aname + '\'' + ", tel='" + tel + '\'' + ", majors=" + majors + '}';
    }

    public String getAid() {
        return aid;
    }

    public void setAid(String aid) {
        this.aid = aid;
    }

    public String getAname() {
        return aname;
    }

    public void setAname(String aname) {
        this.aname = aname;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

    public Set<Major> getMajors() {
        return majors;
    }

    public void setMajors(Set<Major> majors) {
        this.majors = majors;
    }
}

/**
* 专业实体类
*/
public class Major {
    private String mid;
    private String mname;
    private String aid;
    private Academy academy;


    public String getMid() {
        return mid;
    }

    public void setMid(String mid) {
        this.mid = mid;
    }

    public String getMname() {
        return mname;
    }

    public void setMname(String mname) {
        this.mname = mname;
    }

    public String getAid() {
        return aid;
    }

    public void setAid(String aid) {
        this.aid = aid;
    }

    public Academy getAcademy() {
        return academy;
    }

    public void setAcademy(Academy academy) {
        this.academy = academy;
    }

    @Override
    public String toString() {
        return "Major{" + "mid='" + mid + '\'' + ", mname='" + mname + '\'' + ", aid='" + aid + '\'' + ", academy=" + academy + '}';
    }
}

在majorDao.xml文件配置如下:

  1. 非延迟加载配置方式
<mapper namespace="pers.qianxian.dao.MajorDao">
  <!-- id表示resultMap的唯一标识,type标识其对应实体类 -->
  <resultMap id="majorMap" type="Major">
    <!-- id标签配置主键 property是实体类属性名,column是对应表的字段名称 -->
    <id property="mid" column="mid"></id>
    <!-- result 标签配置非主键字段 property是实体类属性名,column是对应表的字段名称 -->
    <result property="mname" column="mname"></result>
    <result property="aid" column="aid"></result>

    <!-- 配置一对一的映射: 普通配置方式 -->
    <!-- property表示实体类属性名 column即外键字段 一定要加javaType(表示property的类型,因为要把    主表的信息封装到这个属性)
	  <association property="academy" column="aid" javaType="Academy">
		<!-- 配置主表的主键字段 -->
		<id property="aid" column="aid"></id>-->
		<!-- 配置主表的非主键字段 -->
		<result property="aname" column="aname"></result>
		<result property="tel" column="tel"></result>
	  </association>
  	</resultMap>

  	<!-- 配合普通配置方式的sql语句 -->
	<select id="findAll" resultMap="majorMap">
		select academies.*,majors.mid,majors.mname
		from majors,academies 
		where majors.aid=academies.aid
	</select>
</mapper>
  1. 延迟加载配置方式(需要在主配置文件中开启延迟加载)
<mapper namespace="pers.qianxian.dao.MajorDao">
  <resultMap id="majorMap" type="Major">
    <id property="mid" column="mid"></id>
    <result property="mname" column="mname"></result>
    <result property="aid" column="aid"></result>

    <!-- 配置一对一的映射: 延迟加载配置方式(注意:select语句就不再需要多表联合查询了)
		select属性配置的是Academy根据id查询的dao层方法名
		column是外键字段名
	 -->
    <association property="academy" column="aid" javaType="Academy"
                 select="pers.qianxian.dao.AcademyDao.findById" />
  </resultMap>

  <!-- 配合延迟加载方式的sql语句 -->
  <select id="findAll" resultMap="majorMap">
    select * from majors
  </select>
</mapper>

四、一对多的关联映射

实体类还是Academy和Major
在AcademyDao.xml中配置如下:

  1. 非延迟记载配置方式
<mapper namespace="pers.qianxian.dao.AcademyDao">
  <resultMap id="academyMap" type="Academy">
    <id property="aid" column="aid"></id>
    <result property="aname" column="aname" />
    <result property="tel" column="tel" />

    <!-- 配置一对多映射: 普通配置方式 -->
    <!-- property配置的是保存多的一方的属性名;ofType配置的是多的一方的实体类名 -->
	<collection property="majors" ofType="Major">
		<!-- 配置多的一方的表的个字段映射关系 -->
		<id property="mid" column="mid" />-->
		<result property="mname" column="mname" />
		<result property="aid" column="aid" />
	</collection>
  </resultMap>

  <!-- 配合普通配置方式使用 -->
  <select id="findAll" resultMap="academyMap">
    select academies.*,majors.mid,majors.mname 
    from academies left outer join majors 
    on academies.aid=majors.aid
  </select>

</mapper>
  1. 延迟加载配置方式(需要在主配置文件开启延迟加载)
<mapper namespace="pers.qianxian.dao.AcademyDao">
  <resultMap id="academyMap" type="Academy">
    <id property="aid" column="aid"></id>
    <result property="aname" column="aname" />
    <result property="tel" column="tel" />

    <!-- 配置一对多的映射:延迟加载配置方式 -->
    <!-- column配置的是根据哪一列来查询多的一方
		 select配置的多的一方根据column字段查询的方法
		 注意:select配置的方法一定呀有一个参数
    -->
    <collection property="majors" ofType="Major" column="aid"
                select="pers.qianxian.dao.MajorDao.findMajorsByAid"/>
  </resultMap>

  <!-- 配合延迟加载配置方式使用 -->
  <select id="findAll" resultMap="academyMap">
    select * from academies
  </select>

</mapper>

五、关于Mybatis缓存

  1. 一级缓存
    在SqlSession中的缓存,当SqlSession关闭时,缓存被清空,也可以用sqlSession.clearCache()来清空以及缓存;(一级缓存直接缓存的是对象,第二次查询不需要再封装成实体类)

  2. 二级缓存
    在SqlSessionFactory,同一个sqlSeesionFactory创建的不通过SqlSession对象共享一个缓存;(二级缓存保存的是“散装数据”,即键值对,封装为实体类的工作还是有)

  3. 配置二级缓存(一级缓存默认是开启的)
    步骤:
    (1)在mybatis主要配置文件中配置如下信息:

    <settings>
      <setting name="cacheEnabled" value="true" />
    </settings>
    

    (2)让某个dao的映射文件(mapper)支持二级缓存:在mapper标签里加入 标签
    (3)让某个查询使用二级缓存:在select标签加上useCache=“true”
    映射文件配置信息如下【(2)(3)步】:

<mapper namespace="dao.StudentDao">
  <cache />
  <select id="findAll" resultType="Student" useCache="true">
    select * from students
  </select>
</mapper>

六、相关运行结果

  1. 关于延迟加载
public class Test {
    public static void main(String[] args) throws IOException {
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(in);
        SqlSession sqlSession = factory.openSession();
        AcademyDao academyDao = sqlSession.getMapper(AcademyDao.class);
        List<Academy> academies = academyDao.findAll();
        for (Academy academy : academies)
            System.out.println(academy);

        sqlSession.commit();
        sqlSession.close();
        in.close();
    }
}

只等到需要用的时候才再次去加载,而没有一次性全部加载
在这里插入图片描述

  1. 关于一级缓存
public class MainTest {
    private InputStream in;
    private SqlSession sqlSession;

    @Before
    public void init() throws IOException {
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = builder.build(in);
        sqlSession = sqlSessionFactory.openSession(true);
    }

    @Test
    public void testStudentDao() {
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
        List<Student> students1 = studentDao.findAll();
        List<Student> students2 = studentDao.findAll();
        Student student1 = null, student2 = null;
        for (Student student : students1)
            if (student.getSid().equals("20200001"))
                student1 = student;
        for (Student student : students2)
            if (student.getSid().equals("20200001"))
                student2 = student;
        System.out.println(student1 == student2);
    }

    @After
    public void destroy() throws IOException {
        sqlSession.close(); // 此时一级缓存会消失
        in.close();
    }
}

可以看到,两次相同的查询,只取数据库查了一次
在这里插入图片描述

  1. 关于二级缓存

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值