MyBatis之枚舉類型

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













發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章