前提・実現したいこと
Springフレームワークで画面からアップロードされたCSVファイルをの中身をDBに登録するシステムを作成しています。
Javaを用いてCSVファイルの中身の値を該当の変数の型に格納できるかCastする前に判定してを行いたいのですが良い方法はないでしょうか?
csvファイルは、Tableのカラムと同じヘッダーを持っていることとします。
###CSVファイルの中身の取得の流れ
(1)画面からアップロード
(2)Controllerクラスで「MultiPartFile file」の引数で受け取りServiceクラスに送る。
(3)Serviceクラスで受け取ったCSVファイルを下記の「getCsvFileDataメソッド」のようにList<String[]>に変換して取得する。
private List<String[]> getCsvFileData(MultiPartFile file){ List<String[]> csvList = new ArrayList<String>(); try { InputStream stream = uploadFile.getInputStream(); Reader reader = new InputStreamReader(stream); BufferedReader buf= new BufferedReader(reader); while((line = buf.readLine()) != null) { //「""data","data2","data3""」のような1行の文字列として扱われるため事前に「"」を置換 line = line.replaceAll("\"", ""); String[] data = line.split(","); csvList.add(data); } line = buf.readLine(); } catch (IOException e) { // 省略 } return csvList; }
試していること
instanceofを使用して、事前にキャストできるか判定する。
String errorFlg = ""; public static void main(String[] args) { // csvの代わり List<String[]> csvList = new ArrayList<>(); // 「userId,userName,Age」のような1行目のヘッダーとして扱って下さい String[] header = {"userId", "userName", "Age"}; // 「A0002,Tanaka,20」のような2行目以降のデータとして扱って下さい String[] data = {"A0001", "Tanaka", "20"}; csvList.add(header); csvList.add(data); for (String[] data : csvList) { for (String a : data) { boolean z = checkInValid(a); System.out.println("結果は"+z+"です。"); } } } /*チェックメソッド*/ private static boolean checkInValid(Object obj) { if (!(obj instanceof Integer)) { errorFlg = "false"; System.out.println(obj + "はだめ"); return false; } System.out.println(obj + "はOK"); return true; }
上記の場合だとdataの「20」をIntegerにCastできるようにしたいのですが、dataがString型のためobjには「"20"」として入ってきてしまうのでどんな値もStringとして扱われてしまいます。
どうにかCastできる値か判定できないでしょうか。
###(補足情報)
DB接続にはMybatisを使用していますので下記のようなSQLをMapper.xmlに記載してます。
information.schemaからカラム名やカラムの型、桁数等を取得してきます。
<select id="selectTableInfo" resultType="SchemaBean"> SELECT * FROM information_schema.columns WHERE table_name =#{tableName} ORDER BY ordinal_position; </select>
上記を使用してテーブルの情報を取得します。
カラムとヘッダーをどう紐づけるかも現状決まっていませんが...
下記のようなかんじでJava側で取得してきます。
String tableName = "testTable"; // こんな感じで取得 List<SchemaBean> tableInfo = mapper.selectTableInfo(tableName);
SchemaBeanクラスにはtableの情報であるカラム名や桁数等の情報を持つデータクラスとなっております。
型チェックは、例えば「試していること」のような「Age」の項目に「20」ではなく「2p0」のような明らかに数値ではない値が入ったりした場合にエラーと何行目どの項目が不正な値なのかを画面に返すために行います。
CAST自体は実際はSQLで行いJavaで下記のようなStringBuilderを使用してsql文を生成し該当の型にswitch文で分岐していCASTの部分を分けていけるようにしていく予定です。
StringBuilder sql = new StringBuilder(); int headerMaxSize = csvData.get(0).length - 1; int count = 0; sql.append("INSERT INTO ") sql.append(testTable); sql.append("VALUES("); for(String[] csvData : csvList){ switch(type){ case "varchar": sql.append("CAST("); sql.append(csvData[count]);//csvの列項目 sql.append(" AS CHAR("): sql.append(桁数); // tableInfoから取得する sql.append(")"); break; ...//各々のパターンだけ作成する予定 } } sql.append(")");
// 上記で生成したSQLを下記のようなかんじで呼び出す予定です。
<insert id="insert" parameterType="string"> #{sql} </insert>
FW/ツールのバージョンなど
Java8
MySQL
Spring
Mybatis
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/04/30 00:53