事象 : You have an error in your SQL syntax
詳細
- 環境
- Windows10 Pro バージョン1909
- mybatis-3.3.0.jar
- mybatis-spring-1.2.2.jar
- Eclipse IDE for Enterprise Java Developers Version: 2020-09 (4.17.0)
- java version "1.8.0_251"
org.springframework.jdbc.BadSqlGrammarException:
### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:
You have an error in your SQL syntax;
check the manual that corresponds to your MySQL server version for the right syntax to use near '<!-- 説明用のコメント -->
GROUP BY DATE_FORMAT(' at line 5
#...省略...
原因 : CDATAセクションはプレーンなテキストとして評価されるため
マッピングファイルに不等号を使うSQLを追加するのでCDATAセクションを使った。
マッピングファイルはXML形式のため、SQL内に「<」や「>」を直接記述することができません。
これは、エンティティ参照文字(<や>など)で代替することもできますが、可読性はあまりよくありません。
数値や日付の大小比較で「<」や「>」を記述したい場合は、SQLの可読性を考慮してCDATAセクションをうまく活用しましょう。
CDATAセクションはプレーンなテキストとして評価されるため、「<」や「>」を直接記述することができます。
Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発(株式会社NTTデータ)|翔泳社の本
どんぐらい囲もうかと思った時に以下サイトを見て、確かにSQL文全部囲んだら見やすい気がした。
改善策②
下の例のようにSELECT句全体を囲んでも良かった。
こっちのほうが可読性は高い。(気がする。)
MyBatisのSQLで不等号の比較演算子を使う - Qiita
あっ、説明用のコメント書こっと・・・そして、実行したらエラーーー
<select id="getHoge" resultType="_int">
<![CDATA[
...省略...
<!-- 説明用のコメント -->
GROUP BY DATE_FORMAT(col_name, '%Y%m')
HAVING COUNT(*) >= 12
]]>
</select>
参考にしている本に書いてあるし・・・XMLのコメント書いてもねぇ・・・
対応 : CDATAセクションの範囲を狭める
<select id="getHoge" resultType="_int">
...省略...
<!-- 説明用のコメント -->
GROUP BY DATE_FORMAT(col_name, '%Y%m')
HAVING COUNT(*) <![CDATA[>=]]> 12
</select>
事象 : Could not resolve type alias
- MyBatisで既存のMapperインターフェースとマッピングファイル(xml)にSQLを追加した
- Tomcatを起動したら警告が大量に出てタイムアウトを起こした
詳細
- 環境
- Windows10 Pro バージョン1909
- mybatis-3.3.0.jar
- mybatis-spring-1.2.2.jar
- Eclipse IDE for Enterprise Java Developers Version: 2020-09 (4.17.0)
- java version "1.8.0_251"
警告: Bean creation exception on non-lazy FactoryBean type check:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'hogeMapper' defined in URL [jar:file:/C:/apps/pleiades/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/my-api/WEB-INF/lib/project-2.20.0-SNAPSHOT.jar!/com/example/HogeMapper.class]:
Unsatisfied dependency expressed through bean property 'sqlSessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'sqlSessionFactory' defined in class path resource [spring/application-context.xml]: Invocation of init method failed; nested exception is org.springframework.core.NestedIOException:
Failed to parse mapping resource: 'URL [jar:file:/C:/apps/pleiades/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/my-api/WEB-INF/lib/project-2.20.0-SNAPSHOT.jar!/mybatis/mapper/MyMapper.xml]'; nested exception is org.apache.ibatis.builder.BuilderException: Error parsing Mapper XML.
Cause: org.apache.ibatis.builder.BuilderException: Error resolving class.
Cause: org.apache.ibatis.type.TypeException: Could not resolve type alias 'NewBean'.
Cause: java.lang.ClassNotFoundException: Cannot find class: NewBean
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.persistence.IMyMapper">
<select id="getNewBeans" resultType="NewBean">
import com.example.domain.NewBean;
public interface IMyMapper {
List<NewBean> getNewBeans();
}
原因 : エイリアスを指定していないのにマッピングファイルにクラス名を指定するから
# 設定ファイルにはTypeAiliasがない!
$ grep -i alias mybatis-config.xml
$
TypeAlias
TypeAliasとは、マッピングファイルで指定するJavaクラスに対して、エイリアス(短縮名)を割り当てる機能です。
TypeAliasを使用しない場合、Javaクラスを完全修飾クラス名(FQCN)で指定する必要があります。
TypeAliasを使用すると、記述効率の向上、記述ミスの削減、マッピングファイルの可読性向上などの効果が期待できます。
Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発(株式会社NTTデータ)|翔泳社の本
対応 : マッピングファイルにパッケージ名まで指定する
大人の事情でmybatis-config.xmlは修正できないのでマピングファイルを修正する。
<select id="getNewBeans" resultType="com.example.domain.NewBean">
事象 : Result Maps collection does not contain value for
- MyBatisで既存のMapperインターフェースとマッピングファイル(xml)にSQLを追加した
- アプリの追加したとことは関係ないとこに接続したらエラー
環境とコンソールのエラー
- 環境
- Windows10 Pro バージョン1909
- mybatis-3.3.0.jar
- mybatis-spring-1.2.2.jar
- Eclipse IDE for Enterprise Java Developers Version: 2020-09 (4.17.0)
- java version "1.8.0_251"
org.apache.ibatis.builder.IncompleteElementException: Could not find result map com.example.IMyMapper.NewBean
at org.apache.ibatis.builder.MapperBuilderAssistant.setStatementResultMap(MapperBuilderAssistant.java:358) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.builder.MapperBuilderAssistant.addMappedStatement(MapperBuilderAssistant.java:296) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode(XMLStatementBuilder.java:109) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.Configuration.buildAllStatements(Configuration.java:718) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.Configuration.hasStatement(Configuration.java:688) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.Configuration.hasStatement(Configuration.java:683) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:183) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:44) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:59) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52) ~[mybatis-3.3.0.jar:3.3.0]
# ...省略...
Caused by: java.lang.IllegalArgumentException: Result Maps collection does not contain value for com.example.IMyMapper.NewBean
at org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:818) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.Configuration.getResultMap(Configuration.java:570) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.builder.MapperBuilderAssistant.setStatementResultMap(MapperBuilderAssistant.java:356) ~[mybatis-3.3.0.jar:3.3.0]
... 86 common frames omitted
原因 : resultMapを指定したのに定義がないから
<resultMap id="NewBean"...
を定義したが、本を読んで・・・resultMap
の定義いらないじゃん!と思って定義だけ消した・・・select
タグの属性はいじらずに・・・。
RsultSetとJavaBeanの暗黙的なマッピング
...省略...
SQL実行結果と戻り値となるオブジェクト間のマッピングはMyBatisにより自動的に行われます。
具体的にはSQL実行結果であるResultSetに含まれるカラム名とメソッドの戻り値のJavaBean型のプロパティ名が一致した場合、そのプロパティに該当のカラム値を格納します。
Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発(株式会社NTTデータ)|翔泳社の本
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.IMyMapper">
<select id="getNewBeans" resultMap="NewBean">
SELECT...
public interface IMyMapper {
List<NewBean> getNewBeans();
}
対応 : selectタグのresultMap属性をresultType属性に変更する
明示的なマッピング(resultMap属性)をやめて暗黙的なマッピング(resultType属性)にかえたら属性を修正しましょう。
<select id="getNewBeans" resultType="NewBean">
事象 : It's likely that neither a Result Type nor a Result Map was specified.
- MyBatisで既存のMapperインターフェースとマッピングファイル(xml)にSQLを追加した
- アプリの追加したとこに接続したらエラー
環境とコンソールのエラー
- 環境
- Windows10 Pro バージョン1909
- mybatis-3.3.0.jar
- mybatis-spring-1.2.2.jar
- Eclipse IDE for Enterprise Java Developers Version: 2020-09 (4.17.0)
- java version "1.8.0_251"
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement 'com.example.IMyMapper.getNewBeans'. It's likely that neither a Result Type nor a Result Map was specified.
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:75) ~[mybatis-spring-1.2.2.jar:1.2.2]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:371) ~[mybatis-spring-1.2.2.jar:1.2.2]
# ...省略...
Caused by: org.apache.ibatis.executor.ExecutorException: A query was run and no Result Maps were found for the Mapped Statement 'com.example.IMyMapper.getNewBeans'. It's likely that neither a Result Type nor a Result Map was specified.
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.validateResultMapsCount(DefaultResultSetHandler.java:234) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.handleResultSets(DefaultResultSetHandler.java:157) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:63) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:78) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:62) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:303) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:154) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:102) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:82) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:120) ~[mybatis-3.3.0.jar:3.3.0]
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:113) ~[mybatis-3.3.0.jar:3.3.0]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_251]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_251]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_251]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_251]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:358) ~[mybatis-spring-1.2.2.jar:1.2.2]
... 82 common frames omitted
原因 : 返却値の型の設定がないから
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.IMyMapper">
<select id="getNewBeans">
public interface IMyMapper {
List<NewBean> getNewBeans();
}
対応 : resultMapかresultTypeを定義する
属性 | 説明 |
---|---|
resultType | このステートメントから返されるオブジェクトの型。完全修飾クラス名またはエイリアス。ステートメントがコレクションを返す場合は、コレクションの型ではなくコレクションに含まれるオブジェクトの型を指定する必要があります。resultType とresultMap は、どちらか一方のみ指定可能です。 |
resultMap | 別の場所で定義されているresultMap を参照します。Result Map は MyBatis の中でも最も強力な機能で、深く理解すれば複雑なマッピングが必要となる様々なケースに対応することができます。resultType とresultMap は、どちらか一方のみ指定可能です。 |
上記表の出典 : MyBatis – MyBatis 3 | Mapper XML ファイル
<!--今回は暗黙的なマッピングができるのでresultType属性を指定する-->
<select id="getNewBeans" resultType="NewBean">