Spring Boot整合Mybatis

集成MyBatis分别介绍注解方式以及XML方式的整合,喜欢哪种方式自己选择

添加依赖

这里需要添加mybatis-spring-boot-starter依赖跟mysql依赖

<!--最新版本,匹配spring Boot1.5 or higher-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.0</version>
</dependency>

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

 

这里不引入spring-boot-starter-jdbc依赖,是由于mybatis-spring-boot-starter中已经包含了此依赖。

博主开始整理的时候发现mybatis-spring-boot-starter有新版本了,这里就集成最新的,匹配Spring Boot1.5版本。

MyBatis-Spring-Boot-Starter依赖将会提供如下:

  • 自动检测现有的DataSource
  • 将创建并注册SqlSessionFactory的实例,该实例使用SqlSessionFactoryBean将该DataSource作为输入进行传递
  • 将创建并注册从SqlSessionFactory中获取的SqlSessionTemplate的实例。
  • 自动扫描您的mappers,将它们链接到SqlSessionTemplate并将其注册到Spring上下文,以便将它们注入到您的bean中。

就是说,使用了该Starter之后,只需要定义一个DataSource即可(application.properties中可配置),它会自动创建使用该DataSource的SqlSessionFactoryBean以及SqlSessionTemplate。会自动扫描你的Mappers,连接到SqlSessionTemplate,并注册到Spring上下文中。

数据源配置

在src/main/resources/application.properties中配置数据源信息。

spring.datasource.url = jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driver-class-name = com.mysql.jdbc.Driver

自定义数据源

Spring Boot默认使用tomcat-jdbc数据源,如果你想使用其他的数据源,比如这里使用了阿里巴巴的数据池管理,除了在application.properties配置数据源之外,你应该额外添加以下依赖:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.0.19</version>
</dependency>

 

修改Application.java

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Autowired
    private Environment env;

    //destroy-method="close"的作用是当数据库连接不使用的时候,就把该连接重新放到数据池中,方便下次使用调用.
    @Bean(destroyMethod =  "close")
    public DataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(env.getProperty("spring.datasource.url"));
        dataSource.setUsername(env.getProperty("spring.datasource.username"));//用户名
        dataSource.setPassword(env.getProperty("spring.datasource.password"));//密码
        dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
        dataSource.setInitialSize(2);//初始化时建立物理连接的个数
        dataSource.setMaxActive(20);//最大连接池数量
        dataSource.setMinIdle(0);//最小连接池数量
        dataSource.setMaxWait(60000);//获取连接时最大等待时间,单位毫秒。
        dataSource.setValidationQuery("SELECT 1");//用来检测连接是否有效的sql
        dataSource.setTestOnBorrow(false);//申请连接时执行validationQuery检测连接是否有效
        dataSource.setTestWhileIdle(true);//建议配置为true,不影响性能,并且保证安全性。
        dataSource.setPoolPreparedStatements(false);//是否缓存preparedStatement,也就是PSCache
        return dataSource;
    }
}

 

ok这样就算自己配置了一个DataSource,Spring Boot会智能地选择我们自己配置的这个DataSource实例。

脚本初始化

CREATE DATABASE /*!32312 IF NOT EXISTS*/`spring` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `spring`;

/*Table structure for table `emp` */

DROP TABLE IF EXISTS `emp`;

CREATE TABLE `emp` (
  `empid` int(11) NOT NULL AUTO_INCREMENT,
  `empname` varchar(20) DEFAULT NULL,
  `password` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`empid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

/*Data for the table `emp` */

insert  into `emp`(`empid`,`empname`,`password`) values (1,'jone','123'),(2,'tom','123'),(3,'lisi','123'),(4,'lisisi','123');

 

实体对象

public class Emp {
    private int empId;
    private String empName;
    private String password;
    // SET和GET方法
}

编写Dao层

接下来,我们分别来介绍下注解方式以及XML配置方式。

方案一:注解方式

Mybatis注解的方式好简单,只要定义一个dao接口,然后sql语句通过注解写在接口方法上。最后给这个接口添加@Mapper注解或者在启动类上添加@MapperScan(“com.it.store.dao”)注解都行。

如下:

package com.it.store.dao;
/**
 * Created by tengj on 2017/4/22.
 * Component注解不添加也没事,只是不加service那边引入LearnMapper会有错误提示,但不影响
 */
@Component
@Mapper
public interface LearnMapper {
    @Insert("insert into learn_resource(author, title,url) values(#{author},#{title},#{url})")
    int add(LearnResouce learnResouce);

    @Update("update learn_resource set author=#{author},title=#{title},url=#{url} where id = #{id}")
    int update(LearnResouce learnResouce);

    @DeleteProvider(type = LearnSqlBuilder.class, method = "deleteByids")
    int deleteByIds(@Param("ids") String[] ids);


    @Select("select * from learn_resource where id = #{id}")
    @Results(id = "learnMap", value = {
            @Result(column = "id", property = "id", javaType = Long.class),
            @Result(property = "author", column = "author", javaType = String.class),
            @Result(property = "title", column = "title", javaType = String.class)
    })
    LearnResouce queryLearnResouceById(@Param("id") Long id);

    @SelectProvider(type = LearnSqlBuilder.class, method = "queryLearnResouceByParams")
    List<LearnResouce> queryLearnResouceList(Map<String, Object> params);

    class LearnSqlBuilder {
        public String queryLearnResouceByParams(final Map<String, Object> params) {
            StringBuffer sql =new StringBuffer();
            sql.append("select * from learn_resource where 1=1");
            if(!StringUtil.isNull((String)params.get("author"))){
                sql.append(" and author like '%").append((String)params.get("author")).append("%'");
            }
            if(!StringUtil.isNull((String)params.get("title"))){
                sql.append(" and title like '%").append((String)params.get("title")).append("%'");
            }
            System.out.println("查询sql=="+sql.toString());
            return sql.toString();
        }

        //删除的方法
        public String deleteByids(@Param("ids") final String[] ids){
            StringBuffer sql =new StringBuffer();
            sql.append("DELETE FROM learn_resource WHERE id in(");
            for (int i=0;i<ids.length;i++){
                if(i==ids.length-1){
                    sql.append(ids[i]);
                }else{
                    sql.append(ids[i]).append(",");
                }
            }
            sql.append(")");
            return sql.toString();
        }
    }
}

需要注意的是,简单的语句只需要使用@Insert、@Update、@Delete、@Select这4个注解即可,但是有些复杂点需要动态SQL语句,就比如上面方法中根据查询条件是否有值来动态添加sql的,就需要使用@InsertProvider、@UpdateProvider、@DeleteProvider、@SelectProvider等注解。

这些可选的 SQL 注解允许你指定一个类名和一个方法在执行时来返回运行 允许创建动态 的 SQL。 基于执行的映射语句, MyBatis 会实例化这个类,然后执行由 provider 指定的方法. 该方法可以有选择地接受参数对象.(In MyBatis 3.4 or later, it’s allow multiple parameters) 属性: type,method。type 属性是类。method 属性是方法名。 注意: 这节之后是对 类的 讨论,它可以帮助你以干净,容于阅读 的方式来构建动态 SQL。

方案二:XML配置方式

xml配置方式保持映射文件的老传统,优化主要体现在不需要实现dao的是实现层,系统会自动根据方法名在映射文件中找对应的sql,具体操作如下:


新建EmpMapper接口,无需具体实现类。

package com.it.store.dao;

import com.it.store.entity.Emp;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
@Mapper
public interface EmpMapper {
    int add(Emp emp);
    int update(Emp emp);
    int delete(int empId);
    List<Emp> queryAll(Emp emp);
    Emp queryById(int empId);
    int login(Emp emp);
}

修改application.properties 配置文件

#指定bean所在包
mybatis.type-aliases-package=com.it.store.entity
#指定映射文件
mybatis.mapperLocations=classpath:mapper/*.xml

 

添加LearnMapper的映射文件
在src/main/resources目录下新建一个mapper目录,在mapper目录下新建EmpMapper.xml文件。

通过mapper标签中的namespace属性指定对应的dao映射,这里指向EmpMapper。

更多mybatis数据访问操作的使用请参考:mybatis官方中文参考文档

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.it.store.dao.EmpMapper">
    <select id="queryById" resultType="Emp" parameterType="int">
    select * from Emp where empid = #{empid}
   </select>
    <insert id="add" parameterType="Emp" >
        insert into emp values(#{empId},#{empName},#{password})
    </insert>
    <update id="update" parameterType="Emp">
        update emp set empName=#{empName},passwrod=#{password} where empid=#{empId}
    </update>
    <delete id="delete" parameterType="int">
        delete from emp where empId=#{empId}
    </delete>
    <select id="queryAll" parameterType="Emp" resultType="Emp">
        select * from emp where 1=1
        <if test="empName!=null">
            and empName like '%{empName}%'
        </if>
    </select>
    <select id="login" parameterType="Emp" resultType="int">
        select * from emp where empName=#{empName} and password=#{password}
    </select>
</mapper>

以上是dao层两种实现方式,以下是通用代码模块

Service层

public interface EmpService {
    int add(Emp emp);
    int update(Emp emp);
    int delete(int empId);
    List<Emp> queryAll(Emp emp);
    Emp queryById(int empId);
    int login(Emp emp);
}

实现类

package com.it.store.service.impl;

import com.it.store.dao.EmpMapper;
import com.it.store.entity.Emp;
import com.it.store.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
@Service
public class EmpServiceImpl implements EmpService {
    private EmpMapper empMapper;
    @Autowired
    public void setEmpMapper(EmpMapper empMapper) {
        this.empMapper = empMapper;
    }

    @Override
    public int add(Emp emp) {
        return empMapper.add(emp);
    }

    @Override
    public int update(Emp emp) {
        return empMapper.update(emp);
    }

    @Override
    public int delete(int empId) {
        return empMapper.delete(empId);
    }

    @Override
    public List<Emp> queryAll(Emp emp) {
        return empMapper.queryAll(emp);
    }

    @Override
    public Emp queryById(int empId) {
        return empMapper.queryById(empId);
    }

    @Override
    public int login(Emp emp) {
        return empMapper.login(emp);
    }
}

Controller层


@Controller
@RequestMapping("/emp")
public class EmpController {
    private EmpService empService;
    @Autowired
    public void setEmpService(EmpService empService) {
        this.empService = empService;
    }

    Logger log= LoggerFactory.getLogger(EmpController.class);
    @RequestMapping(value = "toLogin",method = RequestMethod.GET)
    public String toLogin(){
        return "login";
    }
    @RequestMapping(value = "login",method = RequestMethod.POST)
    @ResponseBody
    public Object login(HttpServletRequest request, HttpServletResponse response){
        log.debug("start to login");
        Map<String,Object> map =new HashMap<>();
        String empName=request.getParameter("empName");
        String password=request.getParameter("password");
        Emp emp=new Emp(0,empName,password);
        int result=empService.login(emp);
        if(result>0){
            request.getSession().setAttribute("user",emp);
            map.put("result","1");
        }else{
            map.put("result","0");
        }
        return map;
    }
    @RequestMapping("/showEmp")
    public ModelAndView showEmp(){
        ModelAndView mav=new ModelAndView("/show");
        List list=new ArrayList<Emp>();
        Emp emp=new Emp();
        list=empService.queryAll(emp);
        mav.addObject("list",list);
        return mav;

    }
    @RequestMapping("/toAdd")
    public String toAdd(){
        log.debug("toAdd");
        return "/add";
    }
    @RequestMapping(value = "/add",method = RequestMethod.POST)
    public String add(Emp emp){
        int result=empService.add(emp);
        if(result>0){
            return "redirect:/emp/showEmp";
        }else{
            return "/toAdd";
        }
    }

 

修改页面是Html页面如果不采用异步要采用Thymeleaf中的th:value的方法来给表单赋值:

<!DOCTYPE html><!--如果没有th:提示可以把改成此外这样就没问题了-->
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta name="description" content=""/>
    <title>修改</title>

    <link rel="stylesheet" href="../static/css/jq22.css"  th:href="@{/css/jq22.css}"/>
</head>
<body>
<!-- begin -->
<div id="login">
    <div class="wrapper">
        <div class="login">
            <form action="update" method="post"  class="container offset1 loginform">

                <div class="pad">
                    <input type="hidden" name="_csrf" value="9IAtUxV2CatyxHiK2LxzOsT6wtBE6h8BpzOmk="/>
                    <div class="control-group">
                        <div class="controls">
                            <label for="empName" class="control-label fa fa-envelope"></label>
                            <input id="empName" th:value='${emp.empName}' type="text" name="empName" placeholder="empName" tabindex="1"
                                   autofocus="autofocus" class="form-control input-medium" />
                        </div>
                    </div>
                    <div class="control-group">
                        <div class="controls">
                            <label for="password" class="control-label fa fa-asterisk"></label>

                            <input id="password" type="password" name="password" placeholder="Password" tabindex="2"
                                   class="form-control input-medium" th:value='${emp.password}'/>
                        </div>
                    </div>
                </div>
                <div class="form-actions">
                    <input type="hidden"   name="empId" th:value="${emp.empId}"/>
                    <button type="submit"  tabindex="4" class="btn btn-primary">提交</button>
                </div>
            </form>
        </div>
    </div>
    <script src="../static/js/jquery.min.js" th:src="@{/js/jquery.min.js}"></script>
</div>
<!-- end -->
</body>
</html>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值