自前でバインドする

前回からの続きですが、ObjectAPI形式で引数を自前でバインドする方法です

Dao012.java
public interface Dao012 {
	@SqlUpdate("insert into table001 (id, name) values (:id, :name)")
	void insert(@BindMap Map<String,Object> map);

	@SqlQuery("select name from table001 where id=:id")
	String findNameById(@Bind("id") int id);
}
Sample018.java
@BindingAnnotation(BindMap.MapBinderFactory.class)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public static @interface BindMap
{
	public static class MapBinderFactory implements BinderFactory
	{
		@Override
		public Binder<BindMap, Map<String,Object>> build(Annotation annotation)
		{
			return new Binder<BindMap, Map<String,Object>>()
			{
				public void bind(SQLStatement<?> q, BindMap bind, Map<String,Object> arg)
				{
					for( Map.Entry<String, Object> pair : arg.entrySet() )
					{
						q.bind(pair.getKey(), pair.getValue());
					}
				}
			};
		}
	}
}

public static void main(String[] args) {
	String url = "jdbc:postgresql://192.168.52.128/jdbi";
	DBI dbi = new DBI(url, "jdbi_user", "jdbi_pass");
	Dao012 dao = dbi.onDemand(Dao012.class);

	Map<String,Object> map = new HashMap<>();
	map.put("id", 2002);
	map.put("name", "name2001");
	map.put("something_param", ""); // 余分なパラメータ

	dao.insert(map);
	System.out.println("id=2001 => " + dao.findNameById(2001)); // name2001
}

いくつか注意点を

  • @Retention(RetentionPolicy.RUNTIME) アノテーションは必須です。JDBIは実行時にアノテーションを探す仕組みになってますので
  • バインドさせる型は「Map」としないとダメで、「Map」だと、id に数値をセットしようとしてエラーになります。
  • たとえ余分なパラメータ(something_param)をバインドしても怒られないようです
  • このサンプルで作成したMap型のバインドは結構よく使うので便利です(自画自賛w)。というかデフォルトで用意してくれててもいいのになぁ