私の同僚がMyBatisを勉強していたとき、彼はCharタイプフィールドをクエリ条件として使用すると、データを見つけることができず、他のタイプのタイプは問題ないという問題に遭遇しました。
使用されるデータベースはOracle、クエリ条件フィールドタイプはchar(50)、Javaコードは文字列タイプに対応します。
後で、トラブルシューティング後、それはOracleで、Charタイプフィールドのコンテンツ長さが十分でない場合、長さが空間の形で自動的に埋められるためです。フィールド名char(5)の場合、値がSGLの場合、Oracleは長さを空間で自動的に埋め、最終的な値はSGLです。
1。解決策:
方法1:最初にTRIM()関数を使用して、値の両側のスペースを削除し、次のような条件付きクエリとして使用します。
select * from data.name =#{name}変更:
select * from data where trim(data.name)=#{name}方法2:フィールドタイプchar()をVarchar2()タイプに変更します。一般的に言えば、char()タイプは、すべての値が同じ長さの場合にのみ使用されます。たとえば、性別フィールドを使用して男性を表すために使用され、1が女性を表すために使用される場合、Char(1)を使用できます。値の長さが固定されていない場合、長くて短いので、char()タイプを使用しないことが最善です。
2. mybatisがnullを返すことを深く理解します
MyBatisフレームワークを脇に置いて、元のJDBCクエリに戻ります。CHARタイプのOracleを条件としてデータに照会する場合、データは値がまったく同じ場合にのみ見つかります。
たとえば、テストテーブルを作成します。
テーブルt_user(user_name char(5));挿入t_user(user_name)values( 'sgl');
select '"'||user_name||'"' from t_user 。 - クエリの結果は「SGL」です。Oracleが2つのスペースを自動的に埋めることがわかります
JDBCの準備方法を介したデータをクエリします。
conn = getConnection(); ps = conn.preparestatement( "select * from t_user where user_name =?"); ps.setString(1、 "sgl"); resustet rs = ps.executequery();
クエリ条件値「SGL」とデータベース値「SGL」が等しくないため、上記の方法でデータを見つけることはできません。
値が「SGL」の場合、データを見つけることができます。
conn = getConnection(); ps = conn.preparestatement( "select * from t_user where user_name =?"); ps.setString(1、 "sgl"); - 長さ5ビット未満の2つのスペースを追加します結果rs = ps.executequery();
TRIM()メソッドを使用する場合、次のようなデータを照会することもできます。
conn = getConnection(); ps = conn.preparestatement( "select * from t_user where trim(user_name)=?"); - 最初にデータベースでuser_nameをDepaseし、次にps.setstring(1、 "sgl"); resultet rs = ps.executequery()を比較してください。
MyBatisに戻ると、同僚のマッパーファイルは次のとおりです。
<select id = "selectbyname" resulttype = "com.entity.data" parametertype = "java.lang.string"> select * from data.name =#{name} </select>主なメソッドコンテンツは次のとおりです。
public static void main(string [] args){applicationContext ctx = new classpathxmlapplicationContext( "applicationContext.xml"); DataService d =(dataService)ctx.getBean( "DataServiceImpl");データデータ= d.SelectByName( "sgl"); System.out.println(data);}実際、ソースコードを表示するか、ログをデバッグレベルに変更することにより、MyBatisの下部では、Queryステートメントが準備されたステートメントを使用して事前補償され、パラメーターが設定されます。
==>準備:select * from data where data.name =?
==>パラメーター:sgl(string)
以前のJDBCクエリに基づいて、理由がわかっているため、MyBatisの問題を理解するのは簡単です。
さらに、MySQLの下では、Charタイプフィールドの値が不十分な場合、値は自動的にスペースで満たされていないようです。それにもかかわらず、値の長さが固定されていない場合、charタイプを使用することはお勧めしません。
JDBCクエリの完全なコードは次のとおりです。
JDBCツールクラス:
パッケージcom.songguoliang.url; import java.sql.connection; Import java.sql.drivermanager; import java.sql.preparedstatement; import java.sql.resultset; Import java.sql.ResultsetMetadata; Import.sql.sql.sql.sql.sql.sql.scl.sql.sql.sql.scl.sql.sql.sql.sql.sql.sql.sql. java.util.arraylist; Import java.util.list; import java.util.resourcebundle;/** * pure jdbc connection data class * @author sgl * */public class purejdbcdao {private static resourcebundle bundle = resourcebundle.getBundle( "jdbc" "); private static int recount = 0; / ***接続を取得* @return*/ private static connection getConnection(){connection conn = null; try {class.forname(bundle.getString( "DriverClassName")); conn = drivermanager.getConnection(bundle.getString( "url")、bundle.getString( "username")、bundle.getString( "password")); } catch(classNotFoundException e){e.printstacktrace(); } catch(sqlexception e){e.printstacktrace(); }最後に{if(null == conn && recount <5){try {thread.sleep(10000); } catch(arturnedexception e){e.printstacktrace(); } recount ++; system.out.println( "database"+recount+"second reconnect"); conn = getConnection(); }} return conn; } / ** * query data * @param sql * @return * / public static list <string []> query(string sql){list <string []> result = new arraylist <string []>();接続conn = null;ステートメントstmt = null; try {//system.out.println(" [purejdbcdao] queryステートメント: " + sql); conn = getConnection(); stmt = conn.createstatement();結果rs = stmt.executequery(sql); Resultsetmetadata rsmeta = rs.getmetadata(); while(rs.next()){int columnnum = rsmeta.getColumnCount(); string [] field = new String [columnnum]; string fieldvalue = null; for(int i = 1; i <= columnnum; i ++){fieldvalue = rs.getString(i); if(fieldvalue == null){fieldvalue = ""; } field [i-1] = fieldvalue; } result.add(field); }} catch(sqlexception e){e.printstacktrace(); }最後に{try {if(stmt!= null){stmt.close(); } if(conn!= null){conn.close(); }} catch(sqlexception e){e.printstacktrace(); }} return result; } public static list <string []> query(string sql、list <string> params){list <string []> result = new arrayList <string []>();接続conn = null; represedStatement PS = null; try {conn = getConnection(); ps = conn.preparestatement(sql); for(int i = 0; i <params.size(); i ++){ps.setString(i+1、params.get(i)); } resultSet rs = ps.executequery(); Resultsetmetadata rsmeta = rs.getmetadata(); while(rs.next()){int columnnum = rsmeta.getColumnCount(); string [] field = new String [columnnum]; string fieldvalue = null; for(int i = 1; i <= columnnum; i ++){fieldvalue = rs.getString(i); if(fieldvalue == null){fieldvalue = ""; } field [i-1] = fieldvalue; } result.add(field); }} catch(sqlexception e){e.printstacktrace(); }最後に{try {if(ps!= null){ps.close(); } if(conn!= null){conn.close(); }} catch(sqlexception e){e.printstacktrace(); }} return result; } / ** * sqlステートメントを実行 * @param sql * / public static void execute(string sql){connection conn = null;ステートメントstmt = null; try {//system.out.println(" [purejdbcdao] sqlステートメント: " + sql); conn = getConnection(); conn.setautocommit(false); stmt = conn.createstatement(); stmt.execute(sql); conn.commit(); } catch(sqlexception e){try {conn.rollback(); } catch(sqlexception e1){e1.printstacktrace(); } e.printstacktrace(); }最後に{try {if(stmt!= null){stmt.close(); } if(conn!= null){conn.close(); }} catch(sqlexception e){e.printstacktrace(); }}}}テストクラス:
パッケージcom.songguoliang; Import java.util.arrays; import java.util.list; import com.songguoliang.url.purejdbcdao; public static void main(string [] args){//list<string [] user_name =? "、arrays.aslist(" sgl ")); //発見されたエントリの数:0 //List<String [] //エントリの数:1リスト<string []> list = purejdbcdao.query( "select * from t_user where trim(user_name)=?"、arrays.aslist( "sgl")); //エントリの数:1 System.out.println( "エントリ数:"+list.size()); }}要約します
上記は、MyBatisがCharタイプフィールドを使用してOracleデータベースを照会したときにNullの問題を解決するために編集者によって導入されたソリューションです。私はそれが誰にでも役立つことを願っています。ご質問がある場合は、メッセージを残してください。編集者は、すべての人に時間内に返信します。 wulin.comのウェブサイトへのご支援ありがとうございます!