上文中我们学习了使用使用xml来编写sql文件,但是后边我博客功能的编写我打算使用xml,这个文件内容冗余,而且后期维护可能会比较麻烦。我选择使用另一种方法,就是使用@Mapper注解来进行Sql的编写。
使用@Mapper注解,我们的sql在对应的java文件中编写即可。就不需要在xml中编写对应的SQL,相对来说方便一些。我个人认为。
使用mapper注解编写sql是mybatis3中增加了使用注解来配置Mapper的新特性,下面是主要介绍其中几个@Provider的使用方式,他们是:@SelectProvider、@UpdateProvider、@InsertProvider和@DeleteProvider。
一:配置
配置也很简单,就按照上文中的配置mybatis使用xml文件那样配置即可。
1 :在项目入口文件中配置@MapperScan
@SpringBootApplication
// 添加这个注解扫描dao文件
@MapperScan(basePackages = "com.springbootblog.dao")
public class SpringBootBlogApplication
{
public static void main(String[] args) {
SpringApplication.run(SpringBootBlogApplication.class, args);
}
}
2 :在dao目录下articleDao.java中编写添加注释@Mapper
package com.springbootblog.dao;
import com.springbootblog.dao.sqlBuilder.ArticleSqlBuilder;
import com.springbootblog.pojo.Article;
import java.util.List;
import com.springbootblog.pojo.IndexArticle;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.SelectProvider;
@Mapper//这个注解表示这是一个mybatis的mapper类,这个类中包含了对数据库的操作方法。
public interface ArticleDao
{
@SelectProvider(type =ArticleSqlBuilder.class, method = "selectBySearchAndPage")
// 获取博客首页数据列表
List<IndexArticle> selectBySearchAndPage(@Param("search") String search, @Param("startNum") Integer page, @Param("limit") Integer limit);
}
配置到这里,就可以在dao目录下的文件中编写SQL代码了。
二:使用注解编写代码
通常我们在业务中需要使用到sql的操作方式,大概只有四种:增删改查。
因此才有了我在文章开头说的@SelectProvider、@UpdateProvider、@InsertProvider和@DeleteProvider
其实道理是一样的,他们分别对应各自的操作,演示一个,剩下的几个就没有问题了。
package com.springbootblog.dao;
import com.springbootblog.dao.sqlBuilder.ArticleSqlBuilder;
import java.util.List;
import com.springbootblog.pojo.IndexArticle;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.SelectProvider;
@Mapper//这个注解表示这是一个mybatis的mapper类,这个类中包含了对数据库的操作方法。
public interface ArticleDao
{
/**
* 获取博客首页数据总条数
* @param search
* @return
*/
long selectBySearchAndPageNum(@Param("search") String search);
/**
* 获取博客首页数据列表
* @param search
* @param page
* @param limit
* @return
*/
@SelectProvider(type =ArticleSqlBuilder.class, method = "selectBySearchAndPage")
List<IndexArticle> selectBySearchAndPage(@Param("search") String search, @Param("startNum") Integer page, @Param("limit") Integer limit);
}
我们注意上方代码中的下面这部分:
@SelectProvider(type =ArticleSqlBuilder.class, method = "selectBySearchAndPage")
List< IndexArticle > selectBySearchAndPage(@Param("search") String search, @Param("startNum") Integer page, @Param("limit") Integer limit);
简单理解就是在ArticleSqlBuilder.java文件中,找selectBySearchAndPage方法即可。
方法返回的是一个list对应的数据类型是IndexArticle类。
ArticleSqlBuilder.java文件代码如下:
package com.springbootblog.dao.sqlBuilder;
import org.apache.ibatis.annotations.Param;
public class ArticleSqlBuilder
{
public String selectBySearchAndPage(@Param("search") final String search, @Param("startNum") final int startNum, final @Param("limit") int limit) {
String where = " ";
if(search != null && !search.equals(""))
{
where = " WHERE p1.arttitle LIKE '%" + search + "%'";
}
String Sql = "SELECT p1.*,DATE_FORMAT(p1.putime,'%Y-%m-%d') AS addtime,p3.cat_name FROM article AS p1 " +
"LEFT JOIN article_info p2 ON p1.id = p2.article_id " +
"LEFT JOIN art_category p3 ON p1.art_cid = p3.id " +
where +
"ORDER BY p1.is_top DESC,p1.sort_no DESC, p1.id DESC " +
"LIMIT " + startNum +", "+ limit;
System.out.println(Sql);
return Sql;
}
}
上边的方法中有三个参数,我这里是分别接受的,这种情况下就需要采用下边的写法,否则可能会报错。
@Param("search") final String search
接收参数也可以使用一个map来统一接收,代码如下所示:
public String selectBySearchAndPage(Map<String, Object> param) {
String where = " ";
if(param.get("search") != null && !param.get("search").equals(""))
{
where = " WHERE p1.arttitle LIKE '%" + param.get("search") + "%'";
}
String Sql = "SELECT p1.*,DATE_FORMAT(p1.putime,'%Y-%m-%d') AS addtime,p3.cat_name FROM article AS p1 " +
"LEFT JOIN article_info p2 ON p1.id = p2.article_id " +
"LEFT JOIN art_category p3 ON p1.art_cid = p3.id " +
where +
"ORDER BY p1.is_top DESC,p1.sort_no DESC, p1.id DESC " +
"LIMIT " + param.get("startNum") +", "+ param.get("limit");
System.out.println(Sql);
return Sql;
}
第二种写法相对代码少了一部分,对参数比较多的方法比较友好。
简单说,这个文件就是拼接sql使用的。
这个文件你放到哪里都可以,只要能引用到即可。
三:注意问题
1:在开发的时候,我先使用xml来拼接的sql,测试没有之后,我又尝试了一下使用@mapper注解来拼接sql,xml中的id和@mapper注解中对应的method是一样的。在运行代码的时候发现报错。没有具体报错的位置,只是显示编译失败。
我很当时很费解到底是哪里出问题了。后来尝试把xml部分的代码注释之后。代码编译就通过了。很诡异。
2:在Mapper接口和@SelectProvide方法类中,不要使用重载,也就是说,不要使用方法名相同参数不同的方法,以避免发生诡异问题。
四:InsertProvider
这里还是需要着重的在介绍一下,InsertProvider这个写入的注解。为啥要介绍他呢,他在写入操作之后,有可能还需要获取刚写入数据的自增主键。
获取自增主键也可以时候注解获取而且还有两种方式,具体用那个,看你喜好。
1 :@selectKey注解,代码如下:
/**
* 添加浏览记录
* @param browse
* @return
*/
@InsertProvider(type =ArticleSqlBuilder.class, method = "addBrowse")
@SelectKey(statement="select last_insert_id()", before=false, keyProperty="id", resultType=Integer.class, keyColumn="id") // keyProperty为对象中你想要的属性名,keyColumn为对应的数据库字段名
Integer addBrowse(Browse browse);
keyProperty为对象中你想要的属性名,keyColumn为对应的数据库字段名
我传入的参数是数据库表的类对象,@SelectKey注解就将获取到的自增主键映射到这个类对象的id属性中
在controller中直接调用类中获取id属性的方法即可
// 获取自增主键
Integer id = browse.getId();
System.out.println(id);
2 :使用@Options注解,代码如下:
/**
* 添加浏览记录
* @param browse
* @return
*/
@InsertProvider(type =ArticleSqlBuilder.class, method = "addBrowse")
@Options(useGeneratedKeys = true, keyProperty = "id")
Integer addBrowse(Browse browse);
原理和@SelectKey注解是一样的。都是将自增主键映射到参数的类对象中。
在controller中直接调用类中获取id属性的方法即可
// 获取自增主键
Integer id = browse.getId();
System.out.println(id);
我一般习惯使用@options注解,代码少。
有好的建议,请在下方输入你的评论。