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. 利用python数据分析panda学习笔记之DataFrame

    2 DataFrame a:通过传入一个等长的列表构成DataFrame 自动加上索引 data={'state':['ohio','ohio','ohio','Nevada','Nevada'], ...

  2. 做一名开源社区的扫地僧——从Bug report到Google Summer of Code(GSoC):从200个bug到5000美金

    今年的软件自由日(SFD),我在广州Linux用户组的线下活动上做了一个分享,主题叫做<做一名开源社区的扫地僧(上)>.我把演讲的内容重新整理扩充, 写出了文字版, 希望可以跟更多朋友分享 ...

  3. Flutter实战视频-移动电商-25.列表页_使用Provide控制子类-1

    25.列表页_使用Provide控制子类-1 主要是二级分类的UI布局 1分15秒 生成我们的右侧动态类 定义list变量 开始写里面的子项,把每一个小的写了 再拼成一个大的 这样我们的小类就写完了 ...

  4. react-redux升级到7.0.x后报错"TypeError: Object(...) is not a function"

    同样一套代码,react-redux 6.0.x 的版本下可以正常运行,在7.0.x的版本下出现报错,而且报错原因实在太难定位了 package.json { ... "react-redu ...

  5. Unity Prefabs

    通过上一期的学习,我们知道为了如何向场景中添加一个物体.问题来了,如果需要对这个立方体进行修改应该怎么做呢?那我们肯定就得修改这段代码,能不能将立方体本身从我们的开发中单独提出来呢?这就涉及到我们今天 ...

  6. 2013 Noip提高组 Day2

    3288积木大赛 正文 题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前 ...

  7. Integrated Metabolomics and Lipidomics Analyses Reveal Metabolic Reprogramming in Human Glioma with IDH1 Mutation (文献分享一组-黄旭蕾)

    题目:Integrated Metabolomics and Lipidomics Analyses Reveal Metabolic Reprogramming in Human Glioma wi ...

  8. 2018全球十大测试工具Top2 Katalon

    引言 由Capgemini,Sogeti和Micro Focus发布的2017-2018年世界质量报告中,Katalon超越老牌测试工具UFT(源自QTP)成为黑马新秀,在全球十大自动化测试工具中排名 ...

  9. word2vec改进之Negative Sampling

    训练网络时往往会对全部的神经元参数进行微调,从而让训练结果更加准确.但在这个网络中,训练参数很多,每次微调上百万的数据是很浪费计算资源的.那么Negative Sampling方法可以通过每次调整很小 ...

  10. 端口渗透·网站渗透过程 --21 ,22,873,3306,6379,8080(8080端口是针对CMS的渗透)

    声明:文章渗透网站为模拟环境,文章只为利用过程 文章为信息收集和端口渗透两部分,21端口为ftp版本漏洞 8080端口为CMS的渗透 信息收集: ·使用扫描工具nmap ,PortScan 对整个网段 ...