mybatis注釈ベースの開発で問題が発生した概要
10594 ワード
ここでは、Mybatisを使用して永続層を開発し、膨大なxmlプロファイルが強力な機能を提供していますが、sql文はxmlファイルで構成され、一定のルールに従う必要があります.xmlプロファイルの代わりに注釈開発を使用できるようになりました.具体的な流れについては、「Java持続化のmyBatis 3」を参照してください.この本では、注釈開発について概説しています.本稿では、実際の開発で発生した問題について説明します.
一.パラメータバインド問題
1.#{}と${}の使用エラー
codingTermは権限に関する文字列であり、「coding like'%33%'」は、#{}を使用してプレースホルダ操作を行う場合、junitユニットテストコンソール印刷
例外はなく、sql文は問題なく、パラメータバインドも問題ありませんが、データベースまたは正しいデータを取得できません.したがって,#{}はプレースホルダを提供する操作であることを考慮すると,${}はsql接合に用いることができ,codingTermは表のフィールドではなく,実体クラスと関係マッピングを形成できないため,プレースホルダを用いて置換後のコンソール印刷を行うことができず,必要なデータを正常に検出することができる.{}はsql文の「?」に相当して占有操作を行う.
**${}を使用してパッチ式codingTermパラメータを使用する場合、@Param("codingTerm")注記を追加する必要があります.そうしないと、エラーが発生します.
二.出力パラメータの問題
出力するパラメータidタイプがintの場合、戻り値タイプもintの場合、コードは大丈夫、junit実行はエラーを報告しないが、自分の望む結果は得られない.idは表のフィールドであるがマッピングされていないクラスのデカプセル化であるため、戻り値を判断するには
これにより、必要なintタイプの値を返して次の判断を行うことができます.もう1つの理由は、クエリのオブジェクトidがnullの場合、intも戻り値タイプとして使用できないためです.
三.@SelectProvider注記の使用
ACSSQLProviderクラスにはsql文が提供されており、SqlBuilderクラスのパッチ仕様sqlを継承することができますが、継承しなくてもパラメータを取得し、sql文を返すことができます.
2つの場合に有効な接合ができない場合は、まず特定のパラメータの値を取得し、append追加を行い、{}を使用しないことができます.次のように
もう1つの問題は、#{alarmtype}でsearchBeanのalarmtype属性を取得するとバインドエラー
一.パラメータバインド問題
1.#{}と${}の使用エラー
@Select("select ad.*,ac.name as name,ac.acsid from acs_door ad left join acs_server ac on ad.serverid = ac.id where #{codingTerm}")
List<AcsDoorBean> getList(@Param("codingTerm")String codingTerm);
codingTermは権限に関する文字列であり、「coding like'%33%'」は、#{}を使用してプレースホルダ操作を行う場合、junitユニットテストコンソール印刷
==>Preparing: select ad.*,ac.name as name,ac.acsid from acs_door ad left join acs_server ac on ad.serverid = ac.id where ?
==> Parameters: ad.coding like '%33%'(String)
<== Total: 0
例外はなく、sql文は問題なく、パラメータバインドも問題ありませんが、データベースまたは正しいデータを取得できません.したがって,#{}はプレースホルダを提供する操作であることを考慮すると,${}はsql接合に用いることができ,codingTermは表のフィールドではなく,実体クラスと関係マッピングを形成できないため,プレースホルダを用いて置換後のコンソール印刷を行うことができず,必要なデータを正常に検出することができる.{}はsql文の「?」に相当して占有操作を行う.
==> Preparing: select ad.*,ac.name as name,ac.acsid from acs_door ad left join acs_server ac on ad.serverid = ac.id where ad.coding like '%33%'
==> Parameters:
<== Columns: id, serverid, deviceid, doorid, doorname, name, comment, doorstate, doorcontrolstate, coding, emapLeft, emapTop, emapId, name, acsid
<== Row: 1, 1, 33, null, null, null, null, null, null, 33, null, null, null, null, null
<== Row: 2, 2, 33, null, null, null, null, null, null, 33, null, null, null,
<== Total: 3
**${}を使用してパッチ式codingTermパラメータを使用する場合、@Param("codingTerm")注記を追加する必要があります.そうしないと、エラーが発生します.
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'codingTerm' in 'class java.lang.String'
二.出力パラメータの問題
@Select("select id from acs_door where doorname=?")
int isNameExistForAdd(@Param("doorname")String doorname);
出力するパラメータidタイプがintの場合、戻り値タイプもintの場合、コードは大丈夫、junit実行はエラーを報告しないが、自分の望む結果は得られない.idは表のフィールドであるがマッピングされていないクラスのデカプセル化であるため、戻り値を判断するには
@Select("select count(id) from acs_door where doorname=?")
int isNameExistForAdd(@Param("doorname")String doorname);
これにより、必要なintタイプの値を返して次の判断を行うことができます.もう1つの理由は、クエリのオブジェクトidがnullの場合、intも戻り値タイプとして使用できないためです.
三.@SelectProvider注記の使用
@SelectProvider(type=AcsSqlProvider.class,method = "getAlarmListSql")
List<AcsAlarmBean> getAlarmList(AcsAlarmSearchBean alarmBean,String codingTerm, String sqlTermDeviceidDoorAlarm);
ACSSQLProviderクラスにはsql文が提供されており、SqlBuilderクラスのパッチ仕様sqlを継承することができますが、継承しなくてもパラメータを取得し、sql文を返すことができます.
public String getAlarmListSql(Map map)
{
AcsAlarmSearchBean searchBean = (AcsAlarmSearchBean) map.get("searchBean");
StringBuilder sql = new StringBuilder()
.append("select aa.*, ad.doorname as doorname from acs_alarm aa")
.append(" left join acs_door ad on ad.deviceid=aa.deviceid")
.append(" where ${codingTerm}")
.append(" and aa.deviceid in ${sqlTermDeviceidDoorAlarm}");
if ((searchBean.getDeviceid() != null) && (!searchBean.getDeviceid().equals("")))
{
sql.append(" and aa.deviceid=#{searchBean.deviceid}");
}
if (searchBean.getAlarmtype() != null)
{
sql.append(" and aa.alarmtype=#{alarmtype}");
}
if (searchBean.getAlarmstate() != null)
{
sql.append(" and aa.alarmstate=#{alarmstate}");
}
if ((searchBean.getAlarmTimeBegin() != null) && (searchBean.getAlarmTimeEnd() != null))
{
sql.append(" and alarmtime>=#{alarmTimeBegin} and alarmtime);
}
sql.append(" order by alarmtime desc ");
return sql.toString();
}
2つの場合に有効な接合ができない場合は、まず特定のパラメータの値を取得し、append追加を行い、{}を使用しないことができます.次のように
public String getAlarmListSql(Map<String, Object> map)
{
AcsAlarmSearchBean searchBean = (AcsAlarmSearchBean) map.get("searchBean");
String codingTerm = (String) map.get("codingTerm");
String sqlTermDeviceidDoorAlarm = (String) map.get("sqlTermDeviceidDoorAlarm");
StringBuilder sql = new StringBuilder()
.append("select aa.*, ad.doorname as doorname from acs_alarm aa")
.append(" left join acs_door ad on ad.deviceid=aa.deviceid")
.append(" where ").append(codingTerm)
.append(" and aa.deviceid in ").append(sqlTermDeviceidDoorAlarm);
もう1つの問題は、#{alarmtype}でsearchBeanのalarmtype属性を取得するとバインドエラー
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.binding.BindingException: Parameter 'alarmtype' not found. Available parameters are [sqlTermDeviceidDoorAlarm, param1, param2, codingTerm, param3, searchBean]
が報告され、#{searchBean.alarmtype}でパラメータを取得する必要があり、パラメータバインド時に#{alarmtype}のソースを認識できず、指定する必要があります.