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提供的解决方式来解决字段名和属性名的映射关系的。

Mybatis Learning Notes 1的更多相关文章

  1. rt-thread learning notes

    rt-thread learning notes 2018-01-15 > 001 具有相同优先级的线程,每个线程的时间片大小都可以在初始化或创建该线程时指定 rt_thread_t rt_th ...

  2. Rust learning notes

    Rust learning notes Rust Version 1.42.0 $ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs ...

  3. D3 learning notes

    D3 https://d3js.org/ 数据驱动文档显示, 利用 SVG HTML CSS技术. D3.js is a JavaScript library for manipulating doc ...

  4. Coursera, Machine Learning, notes

      Basic theory (i) Supervised learning (parametric/non-parametric algorithms, support vector machine ...

  5. 【Learning Notes】线性链条件随机场(CRF)原理及实现

    1. 概述条件随机场(Conditional Random Field, CRF)是概率图模型(Probabilistic Graphical Model)与区分性分类( Discriminative ...

  6. SQL Learning Notes

    Sams Teach Yourself SQL in 10 Minutes

  7. go learning notes

    1)  cgo $go install test.go # command-line-arguments /usr/bin/ld: unrecognized option '--build-id=no ...

  8. Java learning notes (1):Basic Knowlege points

    Basic Knowlege points: 1: it's necessary that there is only one public class in per .java file 2: .j ...

  9. Python Django Learning Notes..

    The first time I came across django was last month.. Since then I was considering it as the better c ...

随机推荐

  1. 微信小程序开发之三元运算符代替wx.if/wx.else

    直接上代码 实现功能为:当fbphotoFirst为空时,src路径为“pic/信息反馈1-1_14.png“,并且点击事件uploadfbphotoFirst有效,否则为路径fbphotoFirst ...

  2. Tomcat注入到系统服务中,实现服务自启动及常驻

    步骤一.打开service.bat 并修改(推荐notepad++):  1.set SERVICE_NAME=Tomcat6(服务名称,可在命令行中通过该名字进行服务的控制(启动/关闭)) 2.se ...

  3. 翻转链表中相邻的k个节点

    示例: 输入:1->2->3->4->5 k=2 输出:2->1->4->3->5 k=3输出:3->2->1->4->5 Py ...

  4. 微信API接口文档

    传送门

  5. 洛谷P3338 [ZJOI2014]力(FFT)

    传送门 题目要求$$E_i=\frac{F_i}{q_i}=\sum_{j=1}^{i-1}\frac{q_j}{(i-j)^2}-\sum_{j=i+1}^n\frac{q_j}{(j-i)^2}$ ...

  6. TCP协议怎么关闭?

    TCP协议是一个面向连接的传输层协议,那如果避免遭到破坏,该怎样正确关闭呢?一般正常关闭TCP连接是采用四次挥手机制,其实主体就两个,客户端和服务器交互传递,且连续四次,传递的东西是FIN数据包和AC ...

  7. kafka 安装部署

    环境:ubuntu 12.04 64位桌面版 解压kafka -0.10.0.0.tgz -C /root/software/ 进入目录 cd kafka_2.-0.10.0.0/ 创建data 目录 ...

  8. AttributedString 图片间距问题

    1.NSMutableAttributedString如何显示图片 NSMutableAttributedString *vipStr = [[NSMutableAttributedString al ...

  9. C 语言实例 - 二进制与十进制相互转换

    C 语言实例 - 二进制与十进制相互转换 C 语言实例 C 语言实例 二进制转与十进制相互转换. 实例 - 二进制转换为十进制 #include <stdio.h> #include &l ...

  10. AtCoder Beginner Contest 051 ABCD题

    A - Haiku Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement As a New Yea ...