zoukankan      html  css  js  c++  java
  • Mybatis高级应用-2

    文章内容简介

    1.回顾
    2.Mybatis配置文件解析
    3.Mybatis映射文件解析
    	ResultMap标签使用
    	自定义返回值处理(Map)
    	关联映射
    	主键映射
    

    一.回顾

    Mybatis是ORM(object relational Mapping)框架.
    解决接口和Mapper文件映射,接口方法和mapper文件中sql语句的映射。
    

    二.Mybatis配置文件解析

    1.typeAliases标签用法

    给封装数据的模型类起别名,目的是为了减少mapper文件中的配置。
    
    <!-- 别名配置 -->
    	<typeAliases>
            <!--给单独的类起别名-->
    		<typeAlias type="model.User" alias="User"/> 
    		<!-- 默认把类名作为该类的别名(大小写没有影响) -->
    		<package name="model"/>
    	</typeAliases>
    

    2.properties标签用法

    用来加载properties属性文件的。
    
    	<properties resource="" url=""></properties>
    	resource:用来加载classess文件夹下的properties属性文件。
    	url:用来加载指定位置的properties属性文件。
    
    也可以不加载外部的properties文件,也可把连接信息直接写在property标签中	
    <properties>
    		<property name="jdbc.driver" value="com.mysql.jdbc.Driver"/>
    		<property name="jdbc.url" value="jdbc:mysql:///javaee"/>
    		<property name="jdbc.username" value="root"/>
    		<property name="jdbc.password" value="tiger"/>
    </properties>
    	
    
    读取值的优先级:
    1.在 properties元素体内指定的属性首先被读取。
    2.然后根据 properties 元素中的 resource 属性读取类路径下属性文件或根据 url 属性指定的路径读取属性文件,
    并覆盖已读取的同名属性。
    3.最后读取作为方法参数传递的属性,并覆盖已读取的同名属性(一般属性文件中的key要有前缀,如jbdc.url)。
    即:
    通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的是 properties
    属性中指定的属性。
    

    3.Settings标签的用法

    用来设置mybatis的全局功能配置。
    
    设置mybatis的日志实现厂商为Log4j
    <!-- 全局功能配置 -->
    	<settings>
    		<!-- 指定日志厂商为LOG4J -->
    		<setting name="logImpl" value="LOG4J"/>
    	</settings>
    

    3.transactionManager标签用法

    设置mybatis的事务管理策略
    
    type的默认取值:
    1.JDBC(默认使用)
    JDBC – 这个配置就是直接使用了 JDBC 的提交和回滚设置,它依赖于从数据源得到的连接来管理事务作用域。
    2.MANAGED
    MANAGED – 这个配置几乎没做什么。它从来不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如
    JEE 应用服务器的上下文)。
    
    注意:
    如果你正在使用 Spring + MyBatis,则没有必要配置事务管理器, 因为 Spring 模块会使用自带的管理器来覆盖前
    面的配置。
    

    4.dataSource标签用法

    设置mybatis中connection对像的获取策略。
    
    有三种内建的数据源类型
    1.UNPOOLED
    这个数据源的实现只是每次被请求时打开和关闭连接。虽然有点慢,但对于在数据库连接可用性方面没有太高要求
    的简单应用程序来说,是一个很好的选择。 不同的数据库在性能方面的表现也是不一样的,对于某些数据库来说,
    使用连接池并不重要,这个配置就很适合这种情形
    2.POOLED
    这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证
    时间。 这是一种使得并发 Web 应用快速响应请求的流行处理方式。
    还可以配置其他关于连接池中对像的管理策略.
    3.JNDI
    这个数据源的实现是为了能在如 EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放
    置一个 JNDI 上下文的引用。
    

    5.mapper标签用法

    引入映射关系(引入mapper文件或接口类)
    
    <!-- 使用相对于类路径的资源引用 -->
    <mappers>
    	<mapper resource="mapper/UserMapper.xml"/>
    ......
    </mappers>
    <!-- 使用完全限定资源定位符(URL) -->
    <mappers>
    	<mapper url="file:///var/mapper/UserMapper.xml"/>
    <mapper url="d:/mappers/UserMapper.xml"/>
    .....
    </mappers>
    <!-- 使用映射器接口实现类的完全限定类名 -->
    <!--注意:1.接口和mapper文件必须同包放置,2接口和Mapper文件命名一致。-->
    <mappers>
    	<mapper class="mapper.UserMapper"/>
    .....
    </mappers>
    <!-- 将包内的映射器接口实现全部注册为映射器 -->
    <!--注意:1.接口和mapper文件必须同包放置,2接口和Mapper文件命名一致。-->
    <mappers>
    	<package name="mapper"/>
    </mappers>
    

    三.Mybatis映射文件解析

    1.ResultMap标签使用

    作用:
    1.当表中字段与对像set和get方法后缀不一致时,可以使用该标签,重新建立映射关系。
    2.当进行多表关联查询时,可以使用该标签封装成java对像。
    注意:如果表中字段和对像set和get方法后缀一致时,mybatis会进行自动映射封装数据。
    
    1.1.对结果集重新定义映射关系
    <!-- 自定义结果集映射 -->
    	<resultMap type="User" id="baseResultMap">
    		<id column="t_id" property="id"/>
    		<result column="t_username" property="username"/>
    		<result column="t_password" property="password"/>
    	</resultMap>
    <!-- resultType与 resultMap只能使用其中之一-->
    	<select id="selectById" parameterType="User" resultMap="baseResultMap">
    		select * from USER where t_id = #{id}
    	</select>
    
    1.2.多表联时,使用该标签进行复杂类型封装
    注意:
      mybatis把多表关联关系分为以下两种
      a.关联一条记录
      b.关联多条记录
      mybatis在对像中表示该关联关系
      a.关联一个对像在类中使用pojo类型对像进行表达
      b.关联多个对像,在类中使用集合进行表达。
    
    方式一:使用Join查询方式

    对像间关联关系表达

    //多联多方
    public class User {
    
    	private int id;
    	private String username;
    	private String password;
    	//关联多方(orders)
    	private List<Orders> list;
       //省略getter和setter方法
    } 
        
    //关联一方
    public class Orders {
    	
    	private int id;
    	private String oname;
    	private int oprice;
    	
    	//不需要出现外键
    	//关联一方(User)
    	private User user;
        //省略getter和setter方法
     }
    

    Mapper文件中关联关系表达

    <!--UserMapper.xml配置-->
    	<resultMap type="User" id="baseResultMap">
    		<id column="id" property="id"/>
    		<result column="username" property="username"/>
    		<result column="password" property="password"/>
    		<!-- 关联集合数据,使用collection标签,其中ofType用来说明集合中的数据类型 -->
    		<collection property="list" ofType="Orders">
    			<id column="oid" property="id"/>
    			<result column="oname" property="oname"/>
    			<result column="oprice" property="oprice"/>
    		</collection>
    	</resultMap>
    
    	<!-- 连接查询:关联多方 -->
    	<select id="selectByJoin" resultMap="baseResultMap2">
    		SELECT u.*,
    		o.id as oid,<!--给列起别名,目的是防止结果集中字段名重复,导致数据封装错误-->
    		o.oname,
    		o.oprice,
    		o.uid
    		FROM USER u 
            LEFT JOIN orders o
    		ON u.id=o.uid
    	</select>
    
    
       <!--OrdersMapper.xml配置-->
    	<resultMap type="Orders" id="baseResultMap">
    		<id property="id" column="oid"/>
    		<result property="oname" column="oname"/>
    		<result property="oprice" column="oprice"/>
    		<!-- 关联一方:使用association标签,其中javaType是对Orders类中pojo包装类型的说明-->
    		<association property="user" javaType="User">
    			<id column="id" property="id"/>
    			<result column="username" property="username"/>
    			<result column="password" property="password"/>
    		</association>
    	</resultMap>
    
    	<select id="selectById" resultMap="baseResultMap" >
    		SELECT 
        	o.id AS oid,
        	o.oname,
       	 	o.oprice,
        	o.uid,
        	u.*
    		FROM orders as o 
            LEFT JOIN USER as u
            ON u.id=o.uid 
            WHERE o.id = #{id}
    	</select>
    
    
    

    接口代码

    //UserMapper接口
    public interface UserMapper {
    	public List<User> selectByJoin();
    }
    
    //OrdersMapper接口
    
    public interface OrdersMapper {
    	public Orders selectById(int oid);
    }
    

    测试代码(略)

    方式二:通过多条select查询方式

    2.主键映射

    当主键是由数据库自增方式生成(mysql|SqlServer),或者是由序列Sequence生成(Oracle),怎么获取当前主键的值。
    自动将映射的主键值赋给jopo的属性.
    
    <!-- 主键映射 -->
    	<insert id="insert" parameterType="User">
    		<selectKey keyProperty="uid" order="AFTER" resultType="java.lang.Integer">
                select LAST_INSERT_ID()
            </selectKey>
    		INSERT INTO zj_user(uname,upassword)VALUES(#{uname},#{upassword})
    	</insert>
    
    

    对像间关联关系表达(同上)

    Mapper文件中关联关系表达

    <!--UserMapper.xml文件配置-->
    <!-- select方式 -->
    <resultMap type="User" id="baseResultMap">
    		<id column="id" property="id"/>
    		<result column="username" property="username"/>
    		<result column="password" property="password"/>
    		<!-- 关联集合数据,其中
    			ofType用来说明集合中的数据类型;
    			select用来调用另一个Mapper文件的select方法
    			column指的是传到其他select语句中的查询键
             -->
    		<collection property="list" ofType="Orders" select="mapper.OrdersMapper.selectByUid" column="id"></collection>
    		
    </resultMap>
    
    <select id="selectById" parameterType="User" resultMap="baseResultMap">
    		select * from USER where id = #{id}
    </select>
    
    
    <!--OrdersMapper.xml配置-->
    <!-- select方式 -->
    	<resultMap type="Orders" id="baseResultMap2">
    		<id property="id" column="oid"/>
    		<result property="oname" column="oname"/>
    		<result property="oprice" column="oprice"/>
    		<!-- 关联一方:其中 javaType是对pojo类型的说明-->
    		<association property="user" javaType="User" select="mapper.UserMapper.selectById"  column="uid"></association>
    	</resultMap>
    
    <select id="selectByUid" resultMap="baseResultMap2">
    			select * from orders where uid = #{uid}
    </select>
    

    接口代码

    //UserMapper接口
    public interface UserMapper {
    	public User selectById();
    }
    
    //OrdersMapper接口
    public interface OrdersMapper {
    	public Orders selectByUid(int uid);
    }
    

    测试代码(略)

    3.鉴别器(discriminator了解)

    根据标识符的值,来判断结果集到底封装到哪个Java对像中。
    

    model类

    //Vihicle类
    public class Vihicle {
    
    	private int id;
    	private int type;
    	private String color;
    	private String name;
    	//省略getter和setter方法
    }
    
    //Bus类
    public class Bus extends Vihicle {
    
    }
    
    //Car类
    public class Car extends Vihicle {
    
    }
                 
    

    VihicleMapper.xml文件

    <mapper namespace="mapper.VihicleMapper">
    
    	<resultMap type="Car" id="carMap"></resultMap>
    	
    	<resultMap type="Bus" id="busMap"></resultMap>
    
    	<resultMap type="Vihicle" id="baseResultMap">
    	
    		<id column="id" property="id"/>
    		<result column="type" property="type"/>
    		<result column="color" property="color"/>
    		<result column="name" property="name"/>
    		<!-- 鉴别器:javaType用来说明column中值的类型;
    			 根据column中type列中的值判断:
    			 如果取值为1,使用carMap进行封装数据,返回值是Car类型
    			 如果取值为2,使用busMap进行封装数据,返回值是Bus类型
     		-->
    		<discriminator javaType="java.lang.Integer" column="type">
    			<case value="1"  resultMap="carMap"></case>
    			<case value="2" resultMap="busMap"></case>
    		</discriminator>
    	
    	</resultMap>
    
    	<select id="selectById" resultMap="baseResultMap">
    		select * from vihicle where id = #{id}
    	</select>
    </mapper>
    

    4.自定义返回值(了解)

    根据Mapper文件的select标签的返回值类型,进行数据的自定义封装处理!
    
    4.1.步骤
    1.重写ResultHandler接口
    2.该实现类中需提供获取处理结果的方法
    注意:只能使用非接口编程方式才能实现
    
    4.2代码如下
    //自定义结果封装处理器,要实现ResultHandler接口
    public class MapResultHandler implements ResultHandler{
    	
    	private final  Map<Integer,User> map= new HashMap();
    
        //该方法会被mybatis上下文重复调用(根据结果集的记录数来确定调用次数)
    	@Override
    	public void handleResult(ResultContext resultcontext) {
    		//1.获取Mapper文件select标签的resultType或resultMap的返回值对该数据作自定义处理,比如封装成Map集合
    		User user = resultcontext.getResultObject();
            
            map.put(user.getId(),user);
            
    	}
    	
        //2.需提供获取返回值的方法
    	public Map getData(){
    		return map;
    	}
    
    }
    

    UserMapper.xml文件

    <select id="selectById" parameterType="User" resultType="User">
    		select * from USER where id = #{id}
    </select>
    

    Service层代码

    public Object findData(int id){
    		
    		SqlSession session = MybatisUtil.findSqlSession();
    		
        	//1.创建自定义结果处理器对像
    		MapResultHandler  handler =new MapResultHandler();
    		
        	//2.这里select没有返回值,方法传参时传入自定义的ResultHandler处理器,将mybatis返回的值交由自定义的ResultHandler去处理,所以ResultHandler中需提供获取返回值的方法;
    		session.select("mapper.UserMapper.selectById",id, handler);
    		
    		session.close();
    		//3.调用实现类中的获取数据的方法
    		return handler.getData();
    		
    	}
    
  • 相关阅读:
    八枚硬币问题
    找出诡异的Bug:数据怎么存不进去
    IKAnalyzer使用停用词词典进行分词
    【Quick-COCOS2D-X 3.3 怎样绑定自己定义类至Lua之四】使用绑定C++至Lua的自己定义类
    iOS 自我检測
    蓝桥杯 BASIC 29 高精度加法(大数)
    二叉树的非递归遍历
    [算法]有趣算法合辑[11-20]
    习惯的力量之四理直气壮的借口?
    《github一天一道算法题》:分治法求数组最大连续子序列和
  • 原文地址:https://www.cnblogs.com/zongJianKun/p/10328933.html
Copyright © 2011-2022 走看看