1. TypeHandler の役割と使用シーン
通常、データベースの開発と運用、クエリ、データの挿入、およびその他の操作を行うと、データ型の不一致の例外が報告されることがあり、データ型が一意ではなく、さまざまな異なるデータ型でなければならないことがわかります。また、プログラミング言語としての Java には独自のデータ型があり、データベースにも独自のデータ型があることを明確にする必要があります。
jdbc データ型: org.apache.ibatis.type.JdbcType この列挙は、すべてのデータベース サポート型です。
Java データ型: int、long、string、...
たとえば、Java の重い日付データがデータベースに挿入されている、特定の種類のデータベースに変換されている必要がある、Java とは無関係である必要があるなど、必ず区別してください。途中で見えないデータ処理を行う操作がいくつかあります。
このときのJavaの型がデータベースのデータ型と同じだとすると、他の言語の日付データをデータベースに挿入する際にどのように解釈すればよいか、例えばC#はデータベースの入力時刻型を操作し、C#はデータ型を操作するJava とは何の関係もありません。したがって、各言語とデータベースの間にはデータ型の関係があります。
考える:
Java とデータベースには独自のデータ型があるため、Java データをデータベースに格納する前に他の操作があるかどうかを確認することはできません。
回答: mybatis フレームワークは、データ型ごとにデフォルトの関係対応を作成します。BaseTypeHandler のすべての実装クラスは、これらのプロセスを実行するためにここにあります。
たとえば、データベースに挿入されたときのJavaの日付はどのタイプのjdbcで、なぜこのタイプなのですか? 途中の具体的な操作は?
回答: DateTypeHandler は、日付データ型の処理を解決するためのものです。
2. TypeHandler の使用
Java と JDBC の間のデータ型変換をカスタマイズする場合、TypeHandler インターフェイスを実装する必要があります.このインターフェイスのソース コードは次のとおりです。
//此接口作用是用于指定jdbc与java的数据类型间对应关系处理。
public interface TypeHandler<T> {
// 保存操作,数据入库之前时数据处理
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
//下面三个则是,从数据库加载数据后,vo对象封装前的数据处理
T getResult(ResultSet rs, String columnName) throws SQLException;
T getResult(ResultSet rs, int columnIndex) throws SQLException;
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
リストフィールドをデータベースに挿入する前に varchar に変換する必要がある場合、つまり list [1,2,3] == "varchar 1,2,3データベースへのプログラムの実装コードは次のとおりです。
1. 型ハンドラの実装クラスを書き、変換規則を定式化する
package com.cjy.mybatis.typehandler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import org.apache.log4j.Logger;
@MappedJdbcTypes(JdbcType.VARCHAR) //数据库类型
@MappedTypes({List.class}) //java数据类型
public class ListTypeHandler implements TypeHandler<List<String>>{
private Logger logger = Logger.getLogger(ListTypeHandler.class);
@Override
public void setParameter(PreparedStatement ps, int i,
List<String> parameter, JdbcType jdbcType) throws SQLException {
logger.info("method ====>>> setParameter");
String hobbys = dealListToOneStr(parameter);
ps.setString(i , hobbys);
}
/**
* 集合拼接字符串
* @param parameter
* @return
*/
private String dealListToOneStr(List<String> parameter){
if(parameter == null || parameter.size() <=0)
return null;
String res = "";
for (int i = 0 ;i < parameter.size(); i++) {
if(i == parameter.size()-1){
res+=parameter.get(i);
return res;
}
res+=parameter.get(i)+",";
}
return null;
}
//
@Override
public List<String> getResult(ResultSet rs, String columnName)
throws SQLException {
logger.info("method ====>>> getResult(ResultSet rs, String columnName)");
return Arrays.asList(rs.getString(columnName).split(","));
}
@Override
public List<String> getResult(ResultSet rs, int columnIndex)
throws SQLException {
logger.info("method ====>>> getResult(ResultSet rs, int columnIndex)");
return Arrays.asList(rs.getString(columnIndex).split(","));
}
@Override
public List<String> getResult(CallableStatement cs, int columnIndex) throws SQLException{
logger.info("method ====>>> getResult(CallableStatement cs, int columnIndex)");
String hobbys = cs.getString(columnIndex);
return Arrays.asList(hobbys.split(","));
}
}
2.mybatis xml ファイルを構成する
<typeHandler javaType="list" jdbcType="VARCHAR" handler="com.cjy.mybatis.typehandler.ListTypeHandler"/>
3. SQL を書く
<select id="selectEmp" resultType="com.cjy.mybatis.entity.Employee" parameterType="int">
select id,user_name userName,gender,email,hobbys,createtime from employee where id = #{id}
</select>
<insert id="saveEmpOne" parameterType="com.cjy.mybatis.entity.Employee" >
<!-- or parameterMap="parameMap" -->
INSERT INTO employee(user_name,gender,email,createtime,hobbys)
VALUES(#{userName},#{gender},#{email},#{createtime,typeHandler=com.cjy.mybatis.typehandler.MyDateTypeHandler},
#{hobbys,typeHandler=com.cjy.mybatis.typehandler.ListTypeHandler})
<!--数据插入前:对hobbys做数据格式转换。 -->
</insert>
4. テストコード
@Test
public void test2(){
SqlSessionFactory sqlSessionFactory = MySqlSessionFacoty.getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
Employee employee = new Employee(null, "yanjiu", "1", "[email protected]", new Date(),Arrays.asList(new String[]{"yuwen","shuxue","yingyu","zhengzhi"}));
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
int saveEmpOne = mapper.saveEmpOne(employee);
System.out.println(saveEmpOne+"-------------------");
openSession.commit();
openSession.close();
}
試験結果:
クエリ データ テスト varchar --> リスト変換::
@Test
public void test5(){
SqlSessionFactory sqlSessionFactory = MySqlSessionFacoty.getSqlSessionFactory();
SqlSession openSession = sqlSessionFactory.openSession();
EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
Employee selectEmp = mapper.selectEmp(10);
System.out.println(selectEmp);
/**数据加载成功
2019-07-24 15:08:02 INFO com.cjy.mybatis.typehandler.ListTypeHandler - method ====>>> getResult(ResultSet rs, String columnName)
2019-07-24 15:08:02 INFO com.cjy.mybatis.typehandler.MyDateTypeHandler - getResult(ResultSet rs, String columnName)....
Employee [id=10, userName=yanjiu, gender=1, [email protected], createtime=Wed Jul 24 15:05:58 CST 2019, hobbys=[yuwen, shuxue, yingyu, zhengzhi]]
*/
}
3. TypeHandlersの登録方法
単一の登録: typeHandler タグは、ハンドラーの完全なクラス名を指定します
複数の登録: 複数の単一の登録方法を指定するか、package タグを使用します
<typeHandlers>
<!-- <typeHandler javaType="list" jdbcType="VARCHAR" handler="com.cjy.mybatis.typehandler.ListTypeHandler"/>
<typeHandler javaType="Date" jdbcType="VARCHAR" handler="com.cjy.mybatis.typehandler.MyDateTypeHandler"/> -->
<package name="com.cjy.mybatis.typehandler"/>
<!--
typeHandler: 单个注册方式
package:多个注册方式
-->
</typeHandlers>