枚举可以让代码变得更为优雅,B格更高。
当然MyBatis也是支持枚举类型的啦。
首先,MyBatis内置了Enum的TypeHandler
TypeHandler |
Java类型 |
JDBC类型 |
EnumTypeHandler |
Enum |
VARCHAR或任何兼容字符串的类型, 存储的是枚举的名称(而不是索引) |
EnumOrdinalTypeHandler |
Enum |
任何兼容NUMERIC或DOUBLE类型 存储的是枚举的索引(而不是名称) |
请着重理解 什么叫枚举的索引,什么叫枚举的名称:
//TODO 写一个例子
public enum Color {
Red(10, "#FF0000"), Green(11, "#00FF00"), BlueGreen(12, "#00FF00");
private int id;
private String rgb;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getRgb() {
return rgb;
}
public void setRgb(String rgb) {
this.rgb = rgb;
}
private Color(int id, String rgb) {
this.id = id;
this.rgb = rgb;
}
public static void main(String[] args) {
System.out.println("枚举的名称:[" + Color.Red.name() + "]");
System.out.println("枚举的索引:[" + Color.Red.ordinal() + "]");
}
}
#output
枚举的名称:[Red]
枚举的索引:[0]
注意,枚举 Sex中的id和rgb并不是所谓的名称和索引。枚举的名称和索引都是枚举类型本身定义的,开发者并不能对齐进行修改。Enum的源码中也将name和ordinal定义为final类型了。
/**
* The name of this enum constant, as declared in the enum declaration.
* Most programmers should use the {@link #toString} method rather than
* accessing this field.
*/
private final String name;
/**
* The ordinal of this enumeration constant (its position
* in the enum declaration, where the initial constant is assigned
* an ordinal of zero).
*
* Most programmers will have no use for this field. It is designed
* for use by sophisticated enum-based data structures, such as
* {@link java.util.EnumSet} and {@link java.util.EnumMap}.
*/
private final int ordinal;
好了,开始正题。
本文主要测试了以下几点:
1.插入MyBatis枚举类型
2.读取MyBatis枚举类型
3.自定义一个枚举Handler
创建一个表:
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sex` int(255) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)
这张表格有4个字段,显然,Sex,非男即女,可以使用枚举类型,定义一个枚举类型
定义枚举类型:
Sex
准备Mybatis基本使用的一些工具,具体可以看我之前的博客http://blog.csdn.net/tjzhuorui/article/details/66997291
好,现在有了MyBatis可以正常使用了,我可以通过SqlSessionFactoryUtil获取SqlSession了.
创建一个POJO,User
public class User {
private int id;
private String name;
private Sex sex;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Sex getSex() {
return sex;
}
public void setSex(Sex sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
创建一个接口UserMapper,定义我们将对数据进行的操作:
public interface UserMapper {
// 使用MyBatis自带的EnumOrdinalTypeHandler,数据库中对应的枚举字段应该为"数字型"
int insertByEnumOrdinalTypeHandler(User user);
User selectByEnumOrdinalTypeHandler(int id);
// 使用MyBatis自带的insertByEnumTypeHandler,数据库中对应的枚举字段应该为"字符串型",本例中,不使用
int insertByEnumTypeHandler(User user);
User selectByEnumTypeHandler(int id);
// 使用自定义的TypeHandler,来实现
int insertByCustomerTypeHandler(User user);
User selectByCustomerTypeHandler(int id);
}
然后,创建user-mapper.xml,并在mybatis-config.xml中关联user-mapper.xml
mybatis-config.xml
<mappers>
<mapper resource="com/robin/mapper/config/user-mapper.xml" />
</mappers>
user-mapper.xml
<mapper namespace="com.robin.mapper.UserMapper">
<insert id="insertByEnumOrdinalTypeHandler" parameterType="com.robin.pojo.User">
insert into t_user
(name,sex,age)values(#{name},#{sex,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler},#{age})
</insert>
</mapper>
然后测试类:
public class TestEnumOrdinalTypeHandler {
public static void main(String[] args) {
SqlSession session = null;
try {
session = SqlSessionFactoryUtil.getSqlSession();
UserMapper mapper = session.getMapper(UserMapper.class);
User user = new User();
user.setSex(Sex.Male);
user.setName("zhangsan");
user.setAge(22);
mapper.insertByEnumOrdinalTypeHandler(user);
session.commit();
} catch (Exception ex) {
ex.printStackTrace();
session.rollback();
} finally {
if (session != null)
session.close();
}
}
}
ok,测试成功,能够看到日志输出:
2017-04-07 11:07:09,005 DEBUG [com.robin.mapper.UserMapper.insertByEnumOrdinalTypeHandler]
==> Preparing: insert into t_user (name,sex,age)values(?,?,?)
2017-04-07 11:07:09,059 DEBUG [com.robin.mapper.UserMapper.insertByEnumOrdinalTypeHandler]
==> Parameters: zhangsan(String), 0(Integer), 22(Integer)
2017-04-07 11:07:09,061 DEBUG [com.robin.mapper.UserMapper.insertByEnumOrdinalTypeHandler]
<== Updates: 1
2017-04-07 11:07:09,062 DEBUG [org.apache.ibatis.transaction.jdbc.JdbcTransaction]
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5ce81285]
然后看数据库:
数据已经插入了。并且能够看到sex为0,id为11
现在读取id为11的数据。
修改user-map.xml,添加查询部分的配置:
<resultMap type="com.robin.pojo.User" id="usermap1">
<result column="id" property="id" />
<result column="name" property="name" />
<result column="sex" property="sex"
typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler" />
<result column="age" property="age" />
</resultMap>
<select id="selectByEnumOrdinalTypeHandler" parameterType="int"
resultMap="usermap1">
select id,name,sex,age from t_user where id=#{id}
</select>
再添加,测试查询的部分:
public class TestEnumOrdinalTypeHandler {
public static void main(String[] args) {
SqlSession session = null;
try {
session = SqlSessionFactoryUtil.getSqlSession();
UserMapper mapper = session.getMapper(UserMapper.class);
// testInsert(session, mapper);
int id = 11;
testSelectOne(session, mapper, id);
session.commit();
} catch (Exception ex) {
ex.printStackTrace();
session.rollback();
} finally {
if (session != null)
session.close();
}
}
private static void testSelectOne(SqlSession session, UserMapper mapper,
int id) {
User user = mapper.selectByEnumOrdinalTypeHandler(id);
System.out.println(user);
}
private static void testInsert(SqlSession session, UserMapper mapper) {
User user = new User();
user.setSex(Sex.Male);
user.setName("zhangsan");
user.setAge(22);
mapper.insertByEnumOrdinalTypeHandler(user);
}
}
得出结果:User [id=11, name=zhangsan, sex=Male, age=22]。
ok结束,那么现在我有的新的需求:
现在我改变定义了,男人是用10表示,女人是用100表示;并且在查询的时候,如果sex字段是10显示男,如果是100显示女,其他字段,返回null;
回顾一下,Mybatis自带的枚举TypeHandler显然已经无法满足我们的需求了,那么现在我们就需要自定义TypeHandler了。
重新定义一下Sex:
public enum Sex {
Male(10, "男"), Female(100, "女");
private int tag;
private String desc;
public String getDesc() {
return desc;
}
public int getTag() {
return tag;
}
public void setTag(int tag) {
this.tag = tag;
}
public void setDesc(String desc) {
this.desc = desc;
}
private Sex(int tag, String desc) {
this.tag = tag;
this.desc = desc;
}
}
可以看到的是,添加了一个tag和的desc.
然后,自定义MyEnumSexTypeHandler implements TypeHandler<Sex>
public class MyEnumSexTypeHandler implements TypeHandler<Sex> {
@Override
public Sex getResult(ResultSet rs, String columnName) throws SQLException {
int tag = rs.getInt(columnName);
for (Sex sex : Sex.values()) {
if (sex.getTag() == tag)
return sex;
}
return null;
}
@Override
public Sex getResult(ResultSet rs, int columnIndex) throws SQLException {
int tag = rs.getInt(columnIndex);
for (Sex sex : Sex.values()) {
if (sex.getTag() == tag)
return sex;
}
return null;
}
@Override
public Sex getResult(CallableStatement cs, int columnIndex)
throws SQLException {
int tag = cs.getInt(columnIndex);
for (Sex sex : Sex.values()) {
if (sex.getTag() == tag)
return sex;
}
return null;
}
@Override
public void setParameter(PreparedStatement pstmt, int index, Sex sex,
JdbcType jdbcType) throws SQLException {
pstmt.setInt(index, sex.getTag());// 这里,不在是使用Sex的oridinal了
}
}
然后在mybatis-config.xml中,注册MyEnumSexTypeHandler
<typeHandlers>
<typeHandler handler="com.robin.type.custom.MyEnumSexTypeHandler" />
</typeHandlers>
然后在user-mapper.xml中,配置sql语句
<insert id="insertByCustomerTypeHandler" parameterType="com.robin.pojo.User">
insert
into t_user
(name,sex,age)values(#{name},#{sex,typeHandler=com.robin.type.custom.MyEnumSexTypeHandler},#{age})
</insert>
最后,写测试类:
public class TestCustomEnumTypeHandler {
public static void main(String[] args) {
SqlSession session = null;
try {
session = SqlSessionFactoryUtil.getSqlSession();
UserMapper mapper = session.getMapper(UserMapper.class);
testInsert(session, mapper);
// int id = 11;
// testSelectOne(session, mapper, id);
session.commit();
} catch (Exception ex) {
ex.printStackTrace();
session.rollback();
} finally {
if (session != null)
session.close();
}
}
private static void testInsert(SqlSession session, UserMapper mapper) {
User user = new User();
user.setName("wang55");
user.setAge(99);
user.setSex(Sex.Female);
mapper.insertByCustomerTypeHandler(user);
}
}
运行,然后看到数据库中确实插入了:
注意看sex,是不是100呀,ok,这样就满足我们的需求了。
关于查询,与MyBatis自带的EnumOrdinalTypeHandler类似,这里,笔者就不粘贴了。感兴趣可以自己去试试。