zoukankan      html  css  js  c++  java
  • Mybatis配置文件

    MyBatis映射文件

    Editor:SimpleWu

    MyBatis真正的核心是在映射文件,由于它的异常强大,如果拿它和相同功能的JDBC代码相比,你会发现它省掉了将近95%的代码。

    MyBatis实体类映射文件

    MyBatis有一下几个顶级元素

    select:映射查询语句

    <select id="findAll" resultType="com.simple.mybatis.entitys.Employee">
    		select * from tal_employee
    </select>
    

    insert:映射插入语句

    使用#{参数属性名}赋值

    <insert id="saveEmp" parameterType="com.simple.mybatis.entitys.Employee">
    		insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
    </insert>
    

    update:映射修改语句

    <update id="updateEmp" parameterType="com.simple.mybatis.entitys.Employee">
    		update tal_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id}
    </update>
    

    delete:映射删除语句

    <delete id="deleteEmp" parameterType="Integer">
    		delete from tal_employee where id=#{id}
    </delete>
    

    sql:可以被其它sql语句重用的sql语句。
    resultMap:是最复杂也是最强大的元素,用来和数据库表和实体类进行映射。

    <resultMap type="com.simple.mybatis.entitys.Employee" id="Employee">
    	<id property="id" column="id"/>
    	<result property="lastName" column="last_name"/>
    	<result property="email" column="email"/>
    	<result property="gender" column="gender"/>
    </resultMap>
    
    <!-- 返回外部resultMap格式的类型。-->
    <select id="findAll" resultMap="Employee">
    	select id,last_name AS lastName,email,gender from tal_employee
    </select>
    

    cache:给定命名空间的缓存配置。
    cache-ref:其它命名空间缓存配置的引用。

    我们结合第一章,使用之前与数据库互交的方式:

    sqlSession.selectList("命名空间.select标签ID");
    sqlSession.selectOne("命名空间.select标签ID");
    sqlSession.update("命名空间.update标签ID", "Object类型参数");
    sqlSession.delete("命名空间.delete标签ID", "Object类型参数");
    sqlSession.insert("命名空间.insert标签ID", "Object类型参数");
    

    增删改必须提交事务:sqlSession.commit();

    使用XML映射文件方式来在执行方法时,由于是通过字符串方式来调用方法,对类型的约束也不是强制性的,可读性较差,这是早期ibatis的调用方式。除此之外Mybatis还提供另外两种实现方式

    MyBatis注解方式

    1. @Select:用来修饰使用查询语句的方法

    2. @Insert:用来修饰使用增加语句的方法、

    3. @Update:用来修饰使用修改修改的方法。

    4. @Delete:用来修饰使用删除语句的方法。

      public interface EmployeeAnnotation {
      @Select("select id,last_name AS lastName,email,gender from tal_employee")
      List findAll();

       @Insert("insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})")
       int saveEmp(Employee employee);
       
       @Update("update tal_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id}")
       boolean updateEmp(Employee employee);
       
       @Delete("elete from tal_employee where id=#{id}")
       long deleteEmp(Integer id);
      

      }

    然后我们需要在mybatis主配置文件中映射这个注解接口

    <!-- 映射注解类 -->
    <mapper class="com.simple.mybatis.dao.EmployeeAnnotation"/>
    
    @Test
    	public void testAnnotation(){
    		SqlSession session = sqlSessionFactory.openSession();
    		EmployeeAnnotation employeeAnnotation = session.getMapper(EmployeeAnnotation.class);
    		Employee employee = new Employee("测试注解增加", "email", "男");
    		employeeAnnotation.saveEmp(employee);
    		//提交事务
    		session.commit();
    		session.close();
    }
    

    使用注解虽然更加方便,但是配置复杂sql语句时较为复杂。所以很多时候采用两种相结合的方式。

    Mybatis接口编程

    我们首先添加一个接口

    public interface EmployeeMapper {
    	List<Employee> findAll();
    	
    	int saveEmp(Employee employee);
    	
    	boolean updateEmp(Employee employee);
    	
    	long deleteEmp(Integer id);
    }
    

    实体类映射文件命名空间(namespace)必须对应接口全名,并且里面的方法需要对应里面增删改查标签ID完成绑定

    <?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="com.simple.mybatis.dao.EmployeeMapper">
    	<resultMap type="com.simple.mybatis.entitys.Employee" id="Employee">
    		<id property="id" column="id"/>
    		<result property="lastName" column="last_name"/>
    		<result property="email" column="email"/>
    		<result property="gender" column="gender"/>
    	</resultMap>
    
    	<!-- 返回外部resultMap格式的类型。-->
    	<select id="findAll" resultMap="Employee">
    		select id,last_name AS lastName,email,gender from tal_employee
    	</select>
    	
    	<insert id="saveEmp" parameterType="com.simple.mybatis.entitys.Employee">
    		insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
    	</insert>
    	
    	<update id="updateEmp" parameterType="com.simple.mybatis.entitys.Employee">
    		update tal_employee set last_name=#{lastName},email=#{email},gender=#{gender} where id=#{id}
    	</update>
    	
    	<delete id="deleteEmp" parameterType="Integer">
    		delete from tal_employee where id=#{id}
    	</delete>
    </mapper>
    

    并且必须在MyBatis主配置文件中加载这个映射文件

    <mappers>
    		<mapper resource="com/simple/mybatis/entitys/EmployeeMapper.xml" />
    </mappers>
    

    使用方式:

    @Test
    	public void test4(){
    		SqlSession session = sqlSessionFactory.openSession();
    		//获取接口。这个接口mybatis会帮我创建代理实现类完成接口与XML映射的绑定
    		EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
    		employeeMapper.deleteEmp(1);
    		session.commit();
    		session.close();
    	}
    

    获取插入后的自动增长主键

    useGeneratedKeys参数只针对 insert 语句生效,默认为 false。当设置为 true 时,表示如果插入的表以自增列为主键,则允许 JDBC 支持自动生成主键,并可将自动生成的主键返回。 keyProperty是要封装给parameterType="com.simple.mybatis.entitys.Employee中的主键ID属性名

    <insert id="saveEmpGetKey" parameterType="com.simple.mybatis.entitys.Employee"
    	useGeneratedKeys="true" keyProperty="id"
    	>
    		insert into tal_employee(last_name,email,gender) values(#{lastName},#{email},#{gender})
    </insert>
    
    @Test
    	public void saveEmpGetKey(){
    		SqlSession session = sqlSessionFactory.openSession();
    		EmployeeMapper employeeMapper = session.getMapper(EmployeeMapper.class);
    		Employee employee = new Employee("自动封装主键", "email", "男");//增加之前主键没赋值
    		employeeMapper.saveEmpGetKey(employee);
    		session.commit();//提交事务
    		System.out.println("增加后主键有值: " + employee.getId());
    		session.close();//关闭资源
    	}
    

    Mybatis参数规则

    一个参数时:

    直接使用#{xxx}来访问参数即可。参数名称任意。例如#{a},#{b}都可以访问参数值。如果是集合(Collection,List,Set)类型,使用集合名称小写作为key值。

    必须接口方法:

    long deleteEmp(Integer emp);
    

    映射文件:

    <delete id="deleteEmp" parameterType="Integer">
    		delete from tal_employee where id=#{id}
    </delete>
    

    在这里可以看到我们是没有给这个赋值的,#{id}我这个属性名也不叫id而是emp。所以一个参数是名字可以任意如果是传入的集合类型

    传入Map参数时取值:

    //接口有方法:long deleteEmp(Map<String, Object> map);
    <delete id="deleteEmp" parameterType="Map">
    		delete from tal_employee where id=#{empID}
    </delete>
    

    我们这里取值是empID,这想想都知道创建一个map.put(“empID”,1)作为参数传入方法调用就行了

    多个参数时:

    1. 默认:就不能使用#{xxx}来访问参数了。当有多个参数时,mybatis会将参数封装为一个map集合,只能通过#{下标}或者#{paramN}的方式来获取值。
    2. 命名参数:明确指定封装参数时手动指定map的key。通过在接口方法上添加@Param("key")来指定参数名称。
    3. 实体类:如果多个参数是封装好的业务类,那么直接传入业务对象即可。可以通过#{属性名}获取属性即可。Map:如果多个参数不是已封装的业务类,那么传入map集合即可。通过#{key}获取对应的value值。

    {}和${}

    MyBatis中,除了可以使用#{}来获取参数的值意外,还可以使用${}来获取参数的值。

    区别:#{}:会以预编译的方式,将参数生成到sql语句中。${}:会直接将值生成到sql语句。

    大多数情况下,我们都是以#{}来获取参数,但是有些地方不支持占位符的地方那么就可以使用${}来获取参数,比如表名。

    resultType返回类型

    1. 对于增删改的方法,Mybatis会自动对结果进行封装,返回int,Boolean,long都可以。
    2. 对于返回实体对象和List集合,resultType可以设置为实体类型。
    3. 如果返回单个对象,也可以封装为Map<String,Object>,resultType设置为map。
    4. 如果返回Map集合对象,比如Map<String,Student>,resultType设置为Student类型,通过@MapKey("id")注解来修饰放入Map中的key值。

    ResultMap标签介绍

    ResultMap的常用子标签

    1. id:映射主键。result:映射普通列。
    2. association:复杂结果映射。
    3. collection:复杂类型的集合映射。
    4. constructor:构造函数注入。

    前面我们的案例我们数据库的字段与实体类的属性基本上一致,或者不一致使用取别名方案解决,可是每条语句都去取别名是非常麻烦的,ResultMap这个标签就很好的解决数据库与实体类字段不对应的问题

    我们新创建一个部门表:

    CREATE TABLE tal_dept(
    	d_id INT PRIMARY KEY AUTO_INCREMENT,
    	d_name VARCHAR(50)
    );
    

    对应实体类:

    public class Dept {
    	private Integer id;
    	private Integer name;
    }
    

    如果我们查询语句直接使用resultType="com.simple.mybatis.entitys.Dept那么毫无疑问我们的实体类中名字不对应是赋值为null的,我们可以ResultMap映射实体类与数据库的对应关系

    <!--配置返回结果,配置数据库字段与类属性的映射-->
    <resultMap type="com.simple.mybatis.entitys.Dept" id="DeptResult">
    		<id column="d_id" property="id"/>
    		<result column="d_name" property="name"/>
    </resultMap>
    <!--使用resultMap使用指向上面返回结果的ID-->
    <select id="getDeptOne" parameterType="Integer" resultMap="DeptResult">
    		select * from tal_dept where d_id = #{id}
    </select>
    

    关系映射

    在数据库中,许多数据是分布在多个表中的,有时候需要将多个表的数据关联起来进行查询。那么在ORM框架中,我们需要处理数据表的映射关系。

    常见的映射关系:

    1. 关联属性映射association
    2. 映射collection映射

    result方式映射属性

    这种方式并不推荐,没有什么重用性

    <resultMap type="com.simple.mybatis.entitys.Employee" id="EmployeeOrDept">
    		<id property="id" column="id"/>
    		<result property="lastName" column="last_name"/>
    		<result property="email" column="email"/>
    		<result property="gender" column="gender"/>
    		<!-- 指定Employee中Dept对象属性 -->
    		<result property="dept.id" column="d_id"/>
    		<result property="dept.name" column="d_name"/>
    </resultMap>
    <select id="getEmployeeOrDeptAll" resultMap="EmployeeOrDept">
    		select * from tal_employee e inner join tal_dept d on e.d_id=d.d_id
    </select>
    

    association映射(分步查询)

    多对一,查询员工获取员工中的部门:

    <resultMap type="com.simple.mybatis.entitys.Employee" id="EmployeeOrDept">
    		<id property="id" column="id"/>
    		<result property="lastName" column="last_name"/>
    		<result property="email" column="email"/>
    		<result property="gender" column="gender"/>
    		<!-- property指定实体类中对象dept 指定发过去的参数column="d_id" 
    			 select指定com.simple.mybatis.dao.DeptMapper映射文件中getDeptOne查询方法
    		 -->
    		<association property="dept" column="d_id" 
    		select="com.simple.mybatis.dao.DeptMapper.getDeptOne"></association>
    </resultMap>
    <!--resultMap指定使用上面定义的返回结果-->
    <select id="getEmployeeOrDeptAll" resultMap="EmployeeOrDept">
    		select * from tal_employee e inner join tal_dept d on e.d_id=d.d_id
    </select>
    

    Collection查询

    一对多,获取部门同时部门中员工也获取:

    <!--部门映射-->
    <resultMap type="com.simple.mybatis.entitys.Dept" id="DeptResult">
    		<id column="d_id" property="id"/>
    		<result column="d_name" property="name"/>
        	<!--property指定Dept中集合属性名 ofType指定集合中属性类型 -->
    		<collection property="Employees" ofType="com.simple.mybatis.entitys.Employee" >
    			<id property="id" column="id"/>
    			<result property="lastName" column="last_name"/>
    			<result property="email" column="email"/>
    			<result property="gender" column="gender"/>
    		</collection>
    </resultMap>
    <select id="getDeptAll" resultMap="DeptResult">
    		select * from tal_dept d left join tal_Employee e on d.d_id = e.d_id
    </select>
    

    Collection嵌套查询

    一对多分布查询

    <resultMap type="com.simple.mybatis.entitys.Dept" id="DeptOrEmployee">
    		<id column="d_id" property="id"/>
    		<result column="d_name" property="name"/>
        	<!--select指定com.simple.mybatis.dao.EmployeeMapper映射文件中的getEmployeeByDeptId-->
    		<collection property="Employees" column="d_id" 	ofType="com.simple.mybatis.entitys.Employee" 
    		select="com.simple.mybatis.dao.EmployeeMapper.getEmployeeByDeptId">
    		</collection>
    	</resultMap>
    <!--com.simple.mybatis.dao.EmployeeMapperXML中方法-->
    <select id="getEmployeeByDeptId" parameterType="Integer" resultType="com.simple.mybatis.entitys.Employee">
    		select * from tal_employee where d_id = #{id}
    	</select>
    

    关联查询和分步查询的区别:

    1. 关联查询一次将多个表的数据查询出来,分步查询通过多次查询获取查询结果。
    2. 配置文件不同,关联查询需要定义额外的映射,分步查询需要定义外键列,和查询的select方法。
    3. 关联查询不支持延迟加载,分步查询支持延迟加载。fetchType="lazy"

    延迟加载

    刚才分布查询是一次将结果查询出来,为了提高效率,mybatis还支持延迟加载技术,等需要用到对象时才进行查询。

    在mybatis主配置文件中配置:

    <!– 通过全局配置文件设置延迟加载-->
    <settings>
    <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。 -->
    <setting name="lazyLoadingEnabled" value="true"/>
    <!-- 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。 -->
    <setting name="aggressiveLazyLoading" value="false"/>
    </settings>
    

    设置级联延迟加载

    <!– 设置延迟加载属性-->
    <association fetchType="lazy"/>
  • 相关阅读:
    《算法笔记》8.1小节——搜索专题->深度优先搜索(DFS)
    [xdoj]1303jlz的刷题黑科技
    [xdoj]1299&1300朱神的烦恼 朱神的序列
    [洛谷]p1996约瑟夫环 &xdoj1311
    [xdoj] 1310 DSKer的卡牌游戏
    [xdoj] 1301&1302 数字计数 数字计数的复仇
    随手快递app开发第十六天
    随手快递app开发第十五天
    随手快递app开发第十四天
    随手快递app开发第十三天
  • 原文地址:https://www.cnblogs.com/SimpleWu/p/9777461.html
Copyright © 2011-2022 走看看