MyBatis之基于XML的属性与列名映射
上一博客主要是对单表的增删改查,比较简单,而且每个属性与table表的列都是一一对应名字也一样,今天主要学习属性与table表列名不一致的处理,主要有两种一是属性与列名不一致,二是枚举的情况,这里暂时考虑的属性与列名不一致只是单表的情况,至于属性如果是其他model涉及表与表之间的关系的放在下一博客。不过先介绍几个其他的知识点。这些都是参考官网http://www.mybatis.org/mybatis-3/zh/index.html,大家也可以直接参考官网的。本篇博客还是在上一篇博客的基础上做的修改。
一、Properties
上一博客创建了一个DBConfig.xml,因为在上一博客只是做了关于数据库的配置,其实它不仅仅可以配置数据库的属性,还可以配置其他的好多属性,比如properties。所以从这篇开始把DBConfig.xml的名字改为了Config.xml。这里为了使用properties,先建了一properties文件:config.properties.
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis
在Config.xml的configuration节点增加如下配置:
<properties resource="config.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
</properties>
如果再配置数据库连接的话就可以使用properties。
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<!-- 配置数据库连接信息 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
还有就是Properties在configuration节点设置的位置的问题,可以按照下图的顺序设置各个属性节点,因为在这个地方我也踩到了坑,就是在使用typeAlias的时候,我把typeAlias放在了mappers下面,然后就报错了。

二、typeAlias
alias别名,这个在sql种也经常用到,在上一博客种我们在UserMapper.xml种如果要参数类型或返回值类型时都会这样Cuiyw.MyBatis.Model.User写上User的全称,其实我们可以使用typeAlias来简化它来减少冗余。这样在用到Cuiyw.MyBatis.Model.User的地方都可以用别名User代替。
<typeAliases>
<typeAlias type="Cuiyw.MyBatis.Model.User" alias="User"/>
</typeAliases>
如果还觉得麻烦,可以直接指定包名就可以了。
<typeAliases>
<package name="Cuiyw.MyBatis.Model"/>
<!-- <typeAlias type="Cuiyw.MyBatis.Model.User" alias="User"/> -->
</typeAliases>
三、属性与列名映射
这是今天的主题,主要是两个内容,一是枚举类型映射,二是属性名与列名不一致怎么映射。
1.自带枚举
如果想使用mybatis自带的枚举类处理,有2种方式,一个是EnumTypeHandler,一个是EnumOrdinalTypeHandler。2者的区别是EnumTypeHandler直接存储name值,而EnumOrdinalTypeHandler会存储enum类里的序号值,此时数据库表字段一般用int类型的处理。
<insert id="addUser" parameterType="User">
<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(name,age,status) values (#{name},#{age},#{status,typeHandler=org.apache.ibatis.type.EnumTypeHandler})
</insert>
<insert id="addUser" parameterType="User">
<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
SELECT LAST_INSERT_ID()
</selectKey>
insert into user(name,age,status) values (#{name},#{age},#{status,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler})
</insert>
上面就是就是使用两种方式实现的新增,下面截图是两种方式在数据库的存储情况。

2.resultMap
上面在sql中的status参数中配置,但对于select的操作没有参数那该怎么办呢?于是resultMap出现了。其实它的作用还有好多,今天主要用它做个简单的例子,同时也演示列名和属性名不一致的情况。虽然先只考虑单表的情况,有时候数据库表的字段名与类的属性名也可能不是一一对应的,这种怎么解决呢?我们可以使用resultMap,用它来做关系映射,这样以后在用到的地方也只需要在select中增加属性resultMap,引用的它id就好也特别方便。这里要注意就是在resultMap设置的typeHandler与在insert中设置的要一致。
<resultMap type="User" id="userResult">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<result column="status" property="status" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
</resultMap>
<select id="getUser" parameterType="int"
resultType="User" resultMap="userResult">
select * from user where id=#{id}
</select>
还是使用昨天的代码,先增加一个,然后把增加的通过id查询出来。

3.自定义枚举
有时候mybatis自带的枚举并不能满足需求,那我们也可以自定义枚举。MyBatis提供了org.apache.ibatis.type.BaseTypeHandler类用于我们自己扩展类型转换器,上面的EnumTypeHandler和EnumOrdinalTypeHandler也都实现了这个接口。
User类
package Cuiyw.MyBatis.Model;
public enum UserState {
DISABLED(0),
AVAILABLE(1);
private int status;
UserState(int status)
{
this.status=status;
}
public static UserState fromValue(int value)
{
for(UserState userState:UserState.values())
{
if(userState.status==value)
{
return userState;
}
}
throw new IllegalArgumentException("Cannot create evalue from value: " + value + "!");
}
public int getStatus()
{
return status;
}
}
EnumStatusHandler自定义枚举类 这里采用的EnumOrdinalTypeHandler模式,保存数字。在用的时候直接引用就好了。
package Cuiyw.MyBatis.Model; import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType; public class EnumStatusHandler extends BaseTypeHandler<UserState> { @Override
public void setNonNullParameter(PreparedStatement ps, int i, UserState parameter, JdbcType jdbcType)
throws SQLException {
// TODO Auto-generated method stub
ps.setInt(i, parameter.getStatus());
} @Override
public UserState getNullableResult(ResultSet rs, String columnName) throws SQLException {
// TODO Auto-generated method stub
return UserState.fromValue(rs.getInt(columnName));
} @Override
public UserState getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
// TODO Auto-generated method stub
return UserState.fromValue(rs.getInt(columnIndex));
} @Override
public UserState getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
// TODO Auto-generated method stub
return UserState.fromValue(cs.getInt(columnIndex));
} }
<resultMap type="User" id="userResult">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<result column="status" property="status" typeHandler="Cuiyw.MyBatis.Model.EnumStatusHandler"/>
</resultMap>
4.自定义枚举优化
上面是针对每个枚举类型创建一个TypeHandler,那如果多的话岂不是很麻烦,那该怎么办呢?有什么优化的方法没?答案当然是有的啦。有单独的一个转到能应用多个,那就会联想的泛型。
1.定义接口
package Cuiyw.MyBatis.Model;
public interface ValuedEnum {
int getValue();
}
2.枚举实现接口
package Cuiyw.MyBatis.Model;
public enum UserState implements ValuedEnum {
DISABLED(0),
AVAILABLE(1);
private int status;
UserState(int status)
{
this.status=status;
}
// public static UserState fromValue(int value)
// {
// for(UserState userState:UserState.values())
// {
// if(userState.status==value)
// {
// return userState;
// }
// }
// throw new IllegalArgumentException("Cannot create evalue from value: " + value + "!");
// }
//
// public int getStatus()
// {
// return status;
// }
public int getValue() {
// TODO Auto-generated method stub
return status;
}
}
3.定义EnumTypeHandler
在ValuedEnumTypeHandler构造函数中使用了getEnumConstants()方法,它以声明顺序返回一个数组,该数组包含构成此 class 对象所表示的枚举类的值,或者在此 class 对象不表示枚举类型时返回 null,这样就可以把枚举值与数字值对应起来放在map中。
package Cuiyw.MyBatis.Model; import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map; import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType; public class ValuedEnumTypeHandler <E extends Enum<E>> extends BaseTypeHandler<E> { private Class<E> type;
private Map<Integer, E> map = new HashMap<Integer, E>(); public ValuedEnumTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
E[] enums = type.getEnumConstants();
if (enums == null) {
throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
}
for (E e : enums) {
ValuedEnum valuedEnum = (ValuedEnum) e;
map.put(valuedEnum.getValue(), e);
}
} @Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
// TODO Auto-generated method stub
ValuedEnum valuedEnum = (ValuedEnum) parameter;
ps.setInt(i, valuedEnum.getValue());
} @Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
int i = rs.getInt(columnName);
if (rs.wasNull()) {
return null;
} else {
return getValuedEnum(i);
}
} @Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
int i = rs.getInt(columnIndex);
if (rs.wasNull()) {
return null;
} else {
return getValuedEnum(i);
}
} @Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
int i = cs.getInt(columnIndex);
if (cs.wasNull()) {
return null;
} else {
return getValuedEnum(i);
}
}
private E getValuedEnum(int value) {
try {
return map.get(value);
} catch (Exception ex) {
throw new IllegalArgumentException(
"Cannot convert " + value + " to " + type.getSimpleName() + " by value.", ex);
}
} }
4.使用
<resultMap type="User" id="userResult">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="age" property="age"/>
<result column="status" property="status" typeHandler="Cuiyw.MyBatis.Model.ValuedEnumTypeHandler"/>
</resultMap>
MyBatis之基于XML的属性与列名映射的更多相关文章
- Mybatis之基于XML的增删改查
这里先吐槽下,写的半天的东西,IE浏览器弹出调试窗口导致写的东西全部没保存,搞得我还要重新用谷歌写,思路全没了,fuck. 前面学习了下spring的DAO层,说起DAO层,那ORM肯定是少不了的,O ...
- MyBatis框架基于XML的配置
什么是MyBatis? 答:它是一个持久层框架 说的太简单了吗?那让我们来看一下官方的文档描述: MyBatis有什么作用呢? 1.持久层的零实现 2.可以自动将数据封装到对象里面不需要手工编写映射的 ...
- Mybatis之基于XML的表之间映射
数据库表之间的关系有3种,一对一.一对多.多对多.既然是ORM,这肯定是必须有的.在学习EF的时候也有涉及,今天就是参考着EF的来学习下MyBatis的表关系映射. 一.准备工作 1.准备Model和 ...
- Mybatis之基于XML的调用存储过程与手动回滚事务
一.调用存储过程 一.返回单个值 1.存储过程准备 这里先创建一个存储过程,传入参数为age,传出参数为count.然后先测试一下是否正确. CREATE DEFINER=`root`@`localh ...
- MyBatis之基于XML的动态SQL
先说下我的梦想,大学的时候一直想着是能开店卖胡辣汤,到目前依然还是我的梦想,上周一家出版社联系我问我有没有时间可以合作出书,这也是我的梦想之一,想了想还是放弃了,至少觉得目前不行,毕竟工作还不到五年, ...
- 基于XML的类的属性的装配
基于XML的属性装配 1.手动装配 <!-- 属性的装配:手动装配 --> <bean id="userService" class="com.neue ...
- mybatis学习笔记(四)-- 为实体类定义别名两种方法(基于xml映射)
下面示例在mybatis学习笔记(二)-- 使用mybatisUtil工具类体验基于xml和注解实现 Demo的基础上进行优化 以新增一个用户为例子,原UserMapper.xml配置如下: < ...
- SpringBoot入门之基于XML的Mybatis
上一博客介绍了下SpringBoot基于注解引入Mybatis,今天介绍基于XML引入Mybatis.还是在上一篇demo的基础上进行修改. 一.Maven引入 这个与上一篇的一样,需要引入mybat ...
- SpringBoot集成Mybatis实现多表查询的两种方式(基于xml)
下面将在用户和账户进行一对一查询的基础上进行介绍SpringBoot集成Mybatis实现多表查询的基于xml的两种方式. 首先我们先创建两个数据库表,分别是user用户表和account账户表 ...
随机推荐
- 《修改代码的艺术》【PDF】下载
<修改代码的艺术>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382309 内容简介 <修改代码的艺术>针对大型的. ...
- 转:iOS开发之多种Cell高度自适应实现方案的UI流畅度分析
本篇博客的主题是关于UI操作流畅度优化的一篇博客,我们以TableView中填充多个根据内容自适应高度的Cell来作为本篇博客的使用场景.当然Cell高度的自适应网上的解决方案是铺天盖地呢,今天我们的 ...
- bzoj 2756: [SCOI2012]奇怪的游戏
Description Blinker最近喜欢上一个奇怪的游戏. 这个游戏在一个 N*M 的棋盘上玩,每个格子有一个数.每次 Blinker 会选择两个相邻 的格子,并使这两个数都加上 1. 现在 B ...
- Clonezilla SE---克隆linux------转载
引入: 本博文将会是<学生机房中的虚拟化>专题中的核心内容.因为,通过本篇博文的讲述,大家可以看到用于网络化批量部署Linux系统的Clonezilla SE搭建的全过程.注意,几乎所有命 ...
- Spring之DAO一
前面博客把bean.aop简单了解了一下,今天主要是了解Spring中DAO层,如果使用传统的JDBC时需要创建连接.打开.执行sql.关闭连接这一系列的步骤,Spring框架对JDBC进行了封装,我 ...
- 5.前端基于react,后端基于.net core2.0的开发之路(5) 配置node层,session设置、获取,请求拦截
1.总结一下 今年,2月份从深圳来到广州,工作到现在,回头看,完成的项目4-5个,公司基本没有懂技术的领导,所以在技术选型上,我们非常的自由,所以内心一直都不满足现状,加上一起工作的小伙伴给力(哈哈哈 ...
- IDEA 环境设置
IDEA环境设置 任何事物都有两面性,如何用好才是关键.IDEA为我们提供了丰富的功能,但不代表默认的配置就适合于你.我们应当根据自己的条件.需求合理的配置,从而驾驭好这匹悍马.让它成为我们编程的利器 ...
- kibana提示“Your Kibana index is out of date, reset it or use the X-Pack upgrade assistant.”
=============================================== 2017/12/15_第1次修改 ccb_warlock = ...
- Python 项目实践三(Web应用程序)第三篇
接着上节的继续学习,现在要显示所有主题的页面 有了高效的网页创建方法,就能专注于另外两个网页了:显示全部主题的网页以及显示特定主题中条目的网页.所有主题页面显示用户创建的所有主题,它是第一个需要使用数 ...
- F和弦大横按
用食指手掌关节顶住. 靠近品柱往上压 右手压住琴尾,这样就很轻松试下C跟F不停转换就快找到感觉 等熟练了,食指自然不会按太上 练得差不多了,手指向琴头倾压,有两个好处 1.手指后面的肉不会碰到弦 2. ...