枚舉可以讓代碼變得更爲優雅,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類似,這裏,筆者就不粘貼了。感興趣可以自己去試試。