使用注解的话,就不需要在配置xml了,只需要写接口就可以了,不过我建议使用注解来写静态sql语句,通过xml来写动态sql,这样更有效率。下面的有些属性什么意思,看过xml配置的基本都能从名字来转换得知它的意思。遵循方式和xml的配置方式都是差不多的。


静态sql情况下的使用

新增方式(@Insert)条件参数是数组,所以可以执行多条新增sql语句,格式就是@Insert(value= {" "," "," "...})


@Insert("insert into t_hus (hus_name,age,fk_wife_id) values (#{h.husbandName},#{h.age},#{h.wife.id})") @Options(useGeneratedKeys=true,keyProperty="h.id") void addHusbandBean(@Param("h") HusbandBean hus); @Param("u")就是给参数取别名,在sql中去调用这个参数



删除方式(@Delete)条件参数是数组,所以可以执行多条删除sql语句,格式就是@Delete(value= {" "," "," "...})


@Delete({"delete from t_wife where id = #{h.wife.id};","delete from t_hus where id = #{h.id};"}) int deleteHusbandBean(@Param("h") HusbandBean hus);



修改方式(@Update)条件参数是数组,所以可以执行多条修改sql语句,格式就是@Update(value= {" "," "," "...})


@Update("update t_user set user_name=#{u.realName},login_name=#{u.userName},`password`=#{u.pwd},fk_role_id=#{u.userGradeValue},update_time=#{u.updateTime} where id=#{u.id}") int updateUser(@Param("u")UserBean userBean);



查询方式(@Select)条件参数是数组,所以可以执行多条查询sql语句,格式就是@Select(value= {" "," "," "...})

1、@ResultType接收数据(就和xml中的resultType一样),遵循规则与xml一样(sql查询出来的列的列别名必须和对象属性一样,保持一致。可以使用Map、基本数据类型、引用数据类型接收数据;如果是Map,取别名就以别名为键,不取别名默认以列名作为键名;如果是其他数据类型,比如本数据类型这些,那么查询的返回结果必须也是与之对应的单一结果,也就是一个结果)


@Select("select id,game_name as gameName from t_game") @ResultType(GameBean.class) List<GameBean> findAllGameBean();



@Param("u")就是给参数取别名,在@Select中我们才能方便去使用这个参数,使用方法就是: 别名.属性

#{ }的作用就是取值的意思,传入对象就用#{别名.属性名};像对象这种层层结构的,比如Map就有这种结构,就可以这样去取值;如果没有这种结构,比如字符串这种单一类型,直接用#{别名}

#{ }和${ }的作用都是取值,区别就是#{ }要进行预编译,而${ }直接编译


2、@Results接收数据(就是xml中的resultMap一样,属性这些就不具体说了)


@Select("select id,player_name from t_player where player_name like concat(#{p.playerName},'%')") @Results({ @Result(id=true,property="id",column="id",javaType=Integer.class), @Result(property="playerName",column="player_name",javaType=String.class) @Result(property="games",javaType=List.class,column="id",many=@Many(fetchType=FetchType.LAZY,select="getGameBeanById"))  }) List<PlayerBean> findPlayerBeanListByObject(@Param("p") PlayerBean player);



动态sql的使用(自定义sql语句)

用来自定义的sql语句的四个注解:@SelectProvider、@InsertProvider、@UpdateProvider、@DeleteProvider;他们就是用来顶替@Select、@Insert、@Update、@Delete的;用了这几个注解,我们就可以使用我们动态拼接的sql语句了。

这四个注解都有两个属性,type指定用的是哪个类,method指定用该类的哪个方法来实现动态sql返回

1、接口定义


@InsertProvider(type=UserSQLProvider.class,method="addBatchUserBean") int addBatchUserBean(@Param("users") List<UserBean> users);



1、新建类和拼接sql的方法(不管方法中的逻辑怎么写,你只需要返回的是一个sql语句就行了)


public class UserSQLProvider {  /** * 无法规避SQL注入的问题 *  * 返回必须是String,因为要返回sql语句; * 用Map<String,Object> params可以获取接口方法的参数,通过键值去获取参数值,就是接口中@Param() 取的别名去获取 * @param params 固定参数 * @return 固定返回 * @throws ParseException */ public String addBatchUserBean(Map<String,Object> params) throws ParseException {  StringBuilder sb = new StringBuilder("insert into t_user(login_name,user_name,user_pwd,age,gender,birthday,create_time) values "); List<UserBean> users = (List<UserBean>) params.get("users");   //这串代码 使用的是直接编译 for (UserBean user : users) { sb.append("('"+user.getLoginName()+"','"+user.getUserName()+"','"+user.getPassword()+"','"+user.getAge()+"','"+user.getGender()+"','"+DateUtil.date2Str(user.getBirthday(), "yyyy-MM-dd")+"',now()),"); }  String sql = sb.toString().substring(0, sb.toString().length() - 1); System.out.println(sql);  return sql; }  }



接口方法使用了@Param注解的话,那么相应sql拼装方法必须接受Map<String, Object>做为参数,通过键值去获取参数值,就是接口中@Param() 取的别名去获取。

对于只有一个参数的情况,可以直接使用,将参数直接传入sql拼接的方法。比如:


@SelectProvider(type = SqlProvider.class, method = "selectUser") @ResultMap("userMap") public User getUser(long userId); public class SqlProvider { public String selectUser(long userId) { return "select * from user where userId=" + userId; } }



@ResultMap是我们去调取xml中的方法,所以如果都用注解了,这样调取岂不是多此一举,用@Results就行了,上面有说明。

接口中如果没有参数传入的话,就sql方法也可以不写参数。


级联关系:

一对一的情况(one=@One):对于丈夫来说,它有一个妻子


@Select("select id,hus_name,age,fk_wife_id from t_hus where id = #{id}") @Results({ @Result(id=true,property="id",column="id",javaType=Integer.class), @Result(property="husbandName",column="hus_name",javaType=String.class), @Result(property="age",column="age",javaType=Integer.class), @Result(property="wife",javaType=WifeBean.class,column="fk_wife_id",one=@One(fetchType=FetchType.LAZY,select="com.gezhi.mybatis01.o2omag.mapper.WifeMapper.getWifeBeanById")) }) HusbandBean getHusbandBeanById(@Param("id")int id);



一对多的情况(many=@Many):对一个老师来说,他对应多个学生


@Select("select id,teacher_name,age from t_teacher where id = #{id}") @Results({ @Result(id=true,property="id",column="id",javaType=Integer.class), @Result(property="teacherName",column="teacher_name",javaType=String.class), @Result(property="age",column="age",javaType=Integer.class), @Result(property="stus",javaType=List.class,column="id",many=@Many(fetchType=FetchType.LAZY,select="findStudentBeanByFkTeacherId")) }) TeacherBean getTeacherBeanById(@Param("id") int id);   @Select("select id,student_name as studentName,age from t_student where fk_teacher_id = #{id}") @ResultType(StudentBean.class) StudentBean findStudentBeanByFkTeacherId(@Param("id") int id);



多对多的情况(需要中间表来关联多对多的两张表,依然用many=@Many,通过中间表来查询另一张表的信息)


@Select("select g.id,g.game_name as gameName from t_game as g,t_player_game as pg where g.id = pg.fk_game_id and fk_player_id = #{id}") @ResultType(GameBean.class) GameBean getGameBeanById(@Param("id") int id);  /** * 根据玩家名称查询 * @param playerName * @return */  @Select("select id,player_name from t_player where player_name like concat(#{p.playerName},'%')") @Results({ @Result(id=true,property="id",column="id",javaType=Integer.class), @Result(property="playerName",column="player_name",javaType=String.class), @Result(property="games",javaType=List.class,column="id",many=@Many(fetchType=FetchType.LAZY,select="getGameBeanById")) }) List<PlayerBean> findPlayerBeanListByObject(@Param("p") PlayerBean player);



鉴别器的情况(其余的不说了,概念什么的,只能说一下父类是宠物pet类,子类是狗类DogBean,还有猫类CatBean)


@Select("select id,pet_name,pet_type,bone,fish from t_pet") @Results({  @Result(id = true, property = "id", column = "id", javaType = Integer.class), @Result(property = "petName", column = "pet_name", javaType = String.class)  }) //鉴别器的配置 @TypeDiscriminator(column = "pet_type", javaType = Integer.class, cases = { @Case(value = "0", type = DogBean.class, results = { @Result(property="bone",column="bone",javaType=Integer.class) }),  @Case(value = "1", type = CatBean.class, results = { @Result(property="fish",column="fish",javaType=Integer.class) }) }) List<PetBean> findAllPetBean();



通过即时加载的方式也调取对象中另一对象的属性:(学生对象中含有一个老师对象)通过这种方式也可完成映射,但是就没有了延时加载的效果。


@Select("select s.id,s.student_name,s.age, t.id as tId,t.teacher_name,t.age as tAge from t_student as s,t_teacher as t where s.fk_teacher_id = t.id") @Results({ @Result(id=true,property="id", column="id",javaType=Integer.class), @Result(property="studentName",column="student_name",javaType=String.class), @Result(property="age",column="age",javaType=Integer.class), @Result(property="teacher.id",column="tId",javaType=Integer.class), @Result(property="teacher.teacherName",column="teacher_name",javaType=String.class), @Result(property="teacher.age",column="tAge",javaType=Integer.class) }) List<StudentBean> findAllStudentBeanAndTeacherBean();