Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Annotations with iBatis (myBatis) for an IN query?

We'd like to use only annotations with MyBatis; we're really trying to avoid xml. We're trying to use an "IN" clause:

@Select("SELECT * FROM blog WHERE id IN (#{ids})")  List<Blog> selectBlogs(int[] ids);  

MyBatis doesn't seem able to pick out the array of ints and put those into the resulting query. It seems to "fail softly" and we get no results back.

It looks like we could accomplish this using XML mappings, but we'd really like to avoid that. Is there a correct annotation syntax for this?

like image 854
dirtyvagabond Avatar asked Aug 07 '10 01:08

dirtyvagabond


People also ask

What is difference between iBATIS and MyBatis?

It is a total makeover of IBATIS. A significant difference between MyBatis and other persistence frameworks is that MyBatis emphasizes the use of SQL, while other frameworks such as Hibernate typically uses a custom query language i.e. the Hibernate Query Language (HQL) or Enterprise JavaBeans Query Language (EJB QL).

How do I use iBATIS?

To define SQL mapping statement using iBATIS, we would add <select> tag in Employee. xml file and inside this tag definition, we would define an "id" which will be used in IbatisRead. java file for executing SQL SELECT query on database.

Does MyBatis use prepared statement?

MyBatis does four main things: It executes SQL safely and abstracts away all the intricacies of JDBC. It maps parameter objects to JDBC prepared statement parameters. It maps rows in JDBC result sets to objects.


2 Answers

I believe the answer is the same as is given in this question. You can use myBatis Dynamic SQL in your annotations by doing the following:

@Select({"<script>",          "SELECT *",           "FROM blog",          "WHERE id IN",             "<foreach item='item' index='index' collection='list'",              "open='(' separator=',' close=')'>",              "#{item}",            "</foreach>",          "</script>"})  List<Blog> selectBlogs(@Param("list") int[] ids); 

The <script> element enables dynamic SQL parsing and execution for the annotation. It must be very first content of the query string. Nothing must be in front of it, not even white space.

Note that the variables that you can use in the various XML script tags follow the same naming conventions as regular queries, so if you want to refer to your method arguments using names other than "param1", "param2", etc... you need to prefix each argument with an @Param annotation.

like image 77
LordOfThePigs Avatar answered Sep 17 '22 04:09

LordOfThePigs


I believe this is a nuance of jdbc's prepared statements and not MyBatis. There is a link here that explains this problem and offers various solutions. Unfortunately, none of these solutions are viable for your application, however, its still a good read to understand the limitations of prepared statements with regards to an "IN" clause. A solution (maybe suboptimal) can be found on the DB-specific side of things. For example, in postgresql, one could use:

"SELECT * FROM blog WHERE id=ANY(#{blogIds}::int[])" 

"ANY" is the same as "IN" and "::int[]" is type casting the argument into an array of ints. The argument that is fed into the statement should look something like:

"{1,2,3,4}" 
like image 42
user199341 Avatar answered Sep 17 '22 04:09

user199341