使用注解的话,就不需要在配置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();