AHugeApe

导航

Mybatis Learning Notes 1

Mybatis Learning Notes

主要的参考是博客园竹山一叶的Blog,这里记录的是自己补充的内容

实体类属性名和数据库不一致的处理

如果是实体类的结果和真正的数据库的column的名称不对应, 需要做一个映射(后面有从数据库映射到实体类的库), 可以直接在sql语句中自己加, 也可以自己在mapper中定义一个对应别名.

基于xml配置和基于注解的两种方式:

xml方式:
建表语句:

CREATE TABLE orders(
    order_id INT PRIMARY KEY AUTO_INCREMENT,
    order_no VARCHAR(20),
    order_price FLOAT
);
INSERT INTO orders(order_no, order_price) VALUES('aaaa', 23);
INSERT INTO orders(order_no, order_price) VALUES('bbbb', 33);
INSERT INTO orders(order_no, order_price) VALUES('cccc', 22);

实体类:


package lyb.domain;

/**
 * Created by lyb on 17-4-13.
 */
public class Order {

    // 建表语句
//    CREATE TABLE orders(
//     order_id INT PRIMARY KEY AUTO_INCREMENT,
//     order_no VARCHAR(20),
//     order_price FLOAT
//    );

    private int id;             //id ===> order_id
    private String orderNo;     //orderNo ===> order_no
    private float price;        //price ===> order_price

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public float getPrice() {
        return price;
    }

    public void setPrice(float price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Order{" +
                "id=" + id +
                ", orderNo='" + orderNo + '\'' +
                ", price=" + price +
                '}';
    }
}

orderMapper.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,namespace的值习惯上设置成包名+sql映射文件名,这样就能够保证namespace的值是唯一的
例如namespace="me.gacl.mapping.orderMapper"就是me.gacl.mapping(包名)+orderMapper(orderMapper.xml文件去除后缀)
 -->
<mapper namespace="me.gacl.mapping.orderMapper">
     <!--
        根据id查询得到一个order对象,使用这个查询是查询不到我们想要的结果的,
        这主要是因为实体类的属性名和数据库的字段名对应不上的原因,因此无法查询出对应的记录
     -->
    <select id="getOrderById" parameterType="int"
        resultType="me.gacl.domain.Order">
        select * from orders where order_id=#{id}
    </select>
     <!--
        根据id查询得到一个order对象,使用这个查询是可以正常查询到我们想要的结果的,
        这是因为我们将查询的字段名都起一个和实体类属性名相同的别名,这样实体类的属性名和查询结果中的字段名就可以一一对应上
     -->
    <select id="selectOrder" parameterType="int"
        resultType="me.gacl.domain.Order">
        select order_id id, order_no orderNo,order_price price from orders where order_id=#{id}
    </select>
     <!--
    根据id查询得到一个order对象,使用这个查询是可以正常查询到我们想要的结果的,
    这是因为我们通过<resultMap>映射实体类属性名和表的字段名一一对应关系 -->
    <select id="selectOrderResultMap" parameterType="int" resultMap="orderResultMap">
        select * from orders where order_id=#{id}
    </select>
    <!--通过<resultMap>映射实体类属性名和表的字段名对应关系 -->
    <resultMap type="me.gacl.domain.Order" id="orderResultMap">
        <!-- 用id属性来映射主键字段 -->
        <id property="id" column="order_id"/>
        <!-- 用result属性来映射非主键字段 -->
        <result property="orderNo" column="order_no"/>
        <result property="price" column="order_price"/>
    </resultMap>
   </mapper>

这里用junit测试的结果为:

package me.gacl.test;
import me.gacl.domain.Order;
import me.gacl.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

public class Test2 {
    @Test
    public void testGetOrderById(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        /**14          * 映射sql的标识字符串,
         * me.gacl.mapping.orderMapper是orderMapper.xml文件中mapper标签的namespace属性的值,
         * getOrderById是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
         */
        String statement = "me.gacl.mapping.orderMapper.getOrderById";//映射sql的标识字符串
        //执行查询操作,将查询结果自动封装成Order对象返回
        Order order = sqlSession.selectOne(statement,1);//查询orders表中id为1的记录
        //使用SqlSession执行完SQL之后需要关闭SqlSession
        sqlSession.close();
        System.out.println(order);//打印结果:null,也就是没有查询出相应的记录
    }

	@Test
    public void testGetOrderById2(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        /**
         * 映射sql的标识字符串,
         * me.gacl.mapping.orderMapper是orderMapper.xml文件中mapper标签的namespace属性的值,
         * selectOrder是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
         */
        String statement = "me.gacl.mapping.orderMapper.selectOrder";//映射sql的标识字符串
        //执行查询操作,将查询结果自动封装成Order对象返回
        Order order = sqlSession.selectOne(statement,1);//查询orders表中id为1的记录
        //使用SqlSession执行完SQL之后需要关闭SqlSession
        sqlSession.close();
        System.out.println(order);//打印结果:Order [id=1, orderNo=aaaa, price=23.0]40     }

    @Test
    public void testGetOrderById3(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        /**
         * 映射sql的标识字符串,
         * me.gacl.mapping.orderMapper是orderMapper.xml文件中mapper标签的namespace属性的值,
         * selectOrderResultMap是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
         */
        String statement = "me.gacl.mapping.orderMapper.selectOrderResultMap";//映射sql的标识字符串
        //执行查询操作,将查询结果自动封装成Order对象返回
        Order order = sqlSession.selectOne(statement,1);//查询orders表中id为1的记录
        //使用SqlSession执行完SQL之后需要关闭SqlSession
        sqlSession.close();
        System.out.println(order);//打印结果:Order [id=1, orderNo=aaaa, price=23.0]
    }
}

同样的使用注解的方式:
OrderMapper.java的内容为:

package lyb.anno_mapper;

import lyb.domain.Order;
import org.apache.ibatis.annotations.*;

/**
 * Created by lyb on 17-4-13.
 */
public interface OrderMapper {

    @Results(id = "orderResult", value = {
            @Result(id = true, property = "id", column = "order_id"),
            @Result(property = "orderNo", column = "order_no"),
            @Result(property = "price", column = "order_price")
    })
    @Select("SELECT * FROM spring_test.orders where order_id=#{id}")
    public Order getOrderWithResultMap(int id);


    @Update("Update spring_test.orders set order_no=#{orderNo}" +
            " where order_id=#{id}")
    public int updateOrderNo(Order order);


    @Select("SELECT order_id id, order_no orderNo, order_price price " +
            "FROM orders WHERE order_id=#{id}")
    public Order selectOrderWithAlias(int id);

    @Select("SELECT * FROM spring_test.orders where order_id=#{orderId}")
    public Order getOrderById(int id);
}

测试代码为:

package lyb;

import lyb.Util.MybatisUtil;
import lyb.anno_mapper.OrderMapper;
import lyb.domain.Order;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

/**
 * Created by lyb on 17-4-13.
 */
public class TestNoConsistency {

    @Test
    public void testNCGetOrderById()
    {
        SqlSession sqlSession = MybatisUtil.getSqlSession(true);
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        Order order = mapper.getOrderById(2);
        sqlSession.close();
        System.out.println(order);
    }

    @Test
    public void testNCUpdateOrderNo()
    {
        SqlSession sqlSession = MybatisUtil.getSqlSession(true);
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        Order order = new Order();
        order.setId(2);
        order.setOrderNo("tt33");
        order.setPrice(87);
        int result = mapper.updateOrderNo(order);
        sqlSession.close();
        System.out.println(result);
    }


    @Test
    public void testNCSelectOrderWithAlias()
    {
        SqlSession sqlSession = MybatisUtil.getSqlSession(true);
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        Order order = mapper.selectOrderWithAlias(2);
        sqlSession.close();
        System.out.println(order);
    }

    @Test
    public void testNCGetOrderWithResultMap()
    {
        SqlSession sqlSession = MybatisUtil.getSqlSession(true);
        OrderMapper mapper = sqlSession.getMapper(OrderMapper.class);
        Order order = mapper.getOrderWithResultMap(2);
        sqlSession.close();
        System.out.println(order);
    }
}

结果同xml, 其实该问题主要在于select的时候不知道如何对应到结果上, 所以得到的结果是null, 但是当把数据库取出的记录起别名或者手工做一个resultmap(xml), 注解对应的方式是写一个@Results对应.

所以对于Update这个方法只要在sql中写好对应关系, 就没有这样的问题.

(别人的总结): 上面的测试代码演示当实体类中的属性名和表中的字段名不一致时,使用MyBatis进行查询操作时无法查询出相应的结果的问题以及针对问题采用的两种办法:

  解决办法一: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致,这样就可以表的字段名和实体类的属性名一一对应上了,这种方式是通过在sql语句中定义别名来解决字段名和属性名的映射关系的。

  解决办法二: 通过来映射字段名和实体类属性名的一一对应关系。这种方式是使用MyBatis提供的解决方式来解决字段名和属性名的映射关系的。

posted on 2018-03-23 16:00  普陀听禅  阅读(132)  评论(0)    收藏  举报