SpringBoot整合MyBatis

------ 既然你都开始整合Mybatis了,我相信基本的SpringBoot项目创建你自己肯定是可以搞定的,所以我在这里就不多赘述了,话不多B,让我们直奔主题

MyBatis---半自动ORM框架

现如今,常见的持久层框架有:HibernateMyBatis , JPA....

相对于Hibernate来说,MyBatis更容易上手一些

今天我就把SpringBoot如何整合Mybatis给大家演示一下,共同学习。

如果有没有接触过这两个技术栈的小伙伴,那你们可以先去康康,稍后再来~~。

这是一段来自百度百科的权威解释

        MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。                MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java对象)映射成数据库中的记录。

项目框架

Maven的pom.xml文件

需要导入的依赖---可以在创建SpringBoot项目时可以勾选导入的技术栈

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <parent>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-parent</artifactId>        <version>2.2.6.RELEASE</version>        <relativePath/> <!-- lookup parent from repository -->    </parent>    <groupId>com.cody</groupId>    <artifactId>sbootmybatis</artifactId>    <version>0.0.1-SNAPSHOT</version>    <name>sbootmybatis</name>    <description>Demo project for Spring Boot</description>    <properties>        <java.version>1.8</java.version>    </properties>    <dependencies>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-thymeleaf</artifactId>        </dependency>        <dependency>            <groupId>org.mybatis.spring.boot</groupId>            <artifactId>mybatis-spring-boot-starter</artifactId>            <version>2.1.2</version>        </dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <scope>runtime</scope>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>            <exclusions>                <exclusion>                    <groupId>org.junit.vintage</groupId>                    <artifactId>junit-vintage-engine</artifactId>                </exclusion>            </exclusions>        </dependency>    </dependencies>    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>        <resources>            <!--此处的配置是识别到mapper.xml文件,也可以在application.properties中配置-->            <resource>                <directory>src/main/java</directory>                <includes>                    <include>**/*.xml</include>                </includes>            </resource>        </resources>    </build></project>

mapper配置文件

UserMapper.xml

==注意文件的位置==

<?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"><!-- namespace:改mapper.xml映射文件的唯一标识并且必须和数据处理层的接口的路径相同--><mapper namespace="com.cody.sbootmybatis.sbootmybatis.mapper.UserMapper"><!--   必须添加property属性 ,区别于是否加主键-->    <resultMap id="user" type="User">        <id column="userid" property="userid" javaType="int" ></id>        <result column="username" property="username" javaType="String" ></result>        <result column="userage" property="userage" javaType="int" ></result>        <result column="userpwd" property="userpwd" javaType="String" ></result>    </resultMap>    <!--id的值必须和数据处理层的接口名一致-->    <!--此处的User-->    <select id="queryAlluser" resultType="User">        select * from  user    </select>    <select id="queryuserbyid"   parameterType="int" resultMap="user" resultType="User">         select * from  user         <trim suffixOverrides="and"  prefixOverrides="and">        <where>              <if test="userid!=null">                 and userid = #{userid}              </if>         </where>         </trim>    </select>    <select id="queryuserbyname" resultType="User" parameterType="string" resultMap="user">        select * from  user        <trim suffixOverrides="and"  prefixOverrides="and">            <where>                <if test="username!=null">                    and username = #{username}                </if>            </where>        </trim>    </select>    <update id="UpdUser" parameterType="User">    </update>    <delete id="DelUser"></delete>    <insert id="AddUser" parameterType="User" >        insert into  user value (${userid},#{username},${userage},#{userpwd})    </insert></mapper>

application.properties的配置

# 端口的配置server.port=8081# 数据库访问配置spring.datasource.type=com.alibaba.druid.pool.DruidDataSourcespring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver#将database_name改成自己的数据库的名称spring.datasource.url=jdbc:mysql://localhost:3306/database_name?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8spring.datasource.username=rootspring.datasource.password=123456

application.yml的配置

# 配置Mybatis的包的别名,在mapper.xml文件中xxxType="xxx" 此处直接可以写实体类的类名即可,不需要将全类名都写上#<select id="queryAlluser" resultType="User">#       select * from  user#    </select>#<select id="queryAlluser" resultType="com.xxx.xxx.entity.User">#       select * from  user#    </select>mybatis:  type-aliases-package: com.xxx.xxx.entity #禁用掉模板缓冲,在开发环境中可以实时的观察到html页面的更改  spring:  thymeleaf:   cache: false

controller

logincontroller.java

/**    loginController    简单的登录测试    与index.html一起使用*/import com.cody.sbootmybatis.sbootmybatis.entity.User;import com.cody.sbootmybatis.sbootmybatis.mapper.UserMapper;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import javax.annotation.Resource;import java.util.Map;/** * @author xxx * @date 2020/5/6 - 10:09 */@Controllerpublic class logincontrollor {    @Resource    private UserMapper userMapper;    @RequestMapping(value = "/user/login" ,method = RequestMethod.POST)    @ResponseBody    public String login(@RequestParam("username") String username ,                        @RequestParam("password")String password , Map<String,Object> map){        User user=userMapper.queryuserbyname(username);        if (username.equals(user.getUsername())&&password.equals(user.getuserpwd())){            return "登录成功";        }        else{            return "登录失败";        }    }}

mycontroller.java

/**    增删改查*/package com.cody.sbootmybatis.sbootmybatis.controllor;import com.cody.sbootmybatis.sbootmybatis.mapper.UserMapper;import com.cody.sbootmybatis.sbootmybatis.entity.User;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController@RequestMapping("/user")public class mycontroller {    @Autowired(required = false)    private UserMapper userMapper;    @RequestMapping(value ={"/queryAlluser"},method = RequestMethod.GET)    /**     *     *     * @return List<User>     *     *     * */    public List<User> queryalluser(){        List<User> list =   userMapper.queryAlluser();        return  list;    }    @RequestMapping(value = {"/queryuserbyid"} , method = RequestMethod.GET)    /**     *     *     * @param userid     * @return user     *     *     */    public User queryuserbyid(String userid){        User user =  userMapper.queryuserbyid(Integer.parseInt(userid));        return user;    }    @RequestMapping(value = {"/adduser"} , method = RequestMethod.GET)    /**     *     *     * @param useri     * @return user     *     *     */    public String adduser(User user){      boolean flag = userMapper.AddUser((User) user);        return flag ?"success":"fail";    }    @RequestMapping(value = {"/Upuserbyid"} , method = RequestMethod.GET)    /**     *     *     * @param userid     * @return user     *     *     */    public String Upuser(User user){        boolean flag = userMapper.UpdUser((User) user);        return flag?"success":"fail";    }    @RequestMapping(value = {"/Deluserbyid"} , method = RequestMethod.GET)    /**     *     *     * @param userid     * @return user     *     *     */    public String Deluserbyid(String userid){        boolean flag  =  userMapper.DelUser(Integer.parseInt(userid));        return flag?"success":"fail";    }}

mapper

package com.cody.sbootmybatis.sbootmybatis.mapper;import com.cody.sbootmybatis.sbootmybatis.entity.User;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Param;import org.apache.ibatis.annotations.Select;import java.util.List;/** * @author Cody * @date 2020/5/2 - 13:25 * @Decription : */@Mapperpublic interface UserMapper {    /**     *查 读取(Retrieve)     * fetch data     * @return List<User>     */    List<User> queryAlluser();    /**     *查 读取(Retrieve)     * fetch data by userid     * @param  userid     * @return User     */    /**        @Select("select * from user where userid = #{userid}")        本人喜欢讲SQL语句写在mapper.xml文件中,这样显得代码比较整齐        在后期开发中,一旦SQL语句变得繁琐起来,不利于维护        但是这样用注解的形式也完全可行,毕竟有些人可能写配置文件可能已经快写吐了    */    User queryuserbyid( int userid);    /**     * 增加(Create)     * add data by user     * @param user     * @return int     */    boolean AddUser(User user);    /**     * 删除(Delete)     * @param id     * @return int     */    boolean DelUser(int id);   /**    * 更新(Update)    * @param user    * @return boolean    */    boolean UpdUser(User user);    User queryuserbyname(String name);}

前端

将index.html文件放在template文件夹下

<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head>    <meta charset="UTF-8">    <title>Title</title></head><body ><form method="post" action="/user/login" >    <input name="username" type="text"  placeholder="请输入用户名"/>    <input type="password" name="password"  />    <input type="submit" th:value="登录"/></form></body></html>

测试

测试登录操作

数据库的信息:

测试CRUD(即增删改查)

查询全部


根据ID查询


增加User

通过?和&传值



注意事项

1.mappe.xml文件的路径包括文件名必须同数据层的接口完全一致

2.application.properties文件和application.yml文件不需要都写,二选一即可,只不过这里我都写了而已


使开发更加便利的IDEA插件

给大家安利一款IDEA插件 : MyBatisX

作用: 在接口中写方法可以直接在mapper.xml文件中写CRUD方法生成相应的标签

图中使用的快捷键是==alt+enter==


MyBatis框架的优点

  1. 与JDBC相比,减少了50%以上的代码量。
  2. MyBatis是最简单的持久化框架,小巧并且简单易学。
  3. MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用。
  4. 提供XML标签,支持编写动态SQL语句。
  5. 提供映射标签,支持对象与数据库的ORM字段关系映射。

MyBatis框架的缺点

  1. SQL语句的编写工作量较大,尤其是字段多、关联表多时,更是如此,对开发人员编写SQL语句的功底有一定要求。
  2. SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

SpringBoot整合Mybatis中遇到的Errors

这是我自己在整合的时候遇到的一些问题,希望自己走过的弯路可以多多帮助到大家。

There was an unexpected error (type=Internal Server Error, status=500).Error attempting to get column 'u_account' from result set. Cause: java.sql.SQLDataException: Cannot determine value type from string '201577D0510' ; Cannot determine value type from string '201577D0510'; nested exception is java.sql.SQLDataException: Cannot determine value type from string '201577D0510'org.springframework.dao.DataIntegrityViolationException: Error attempting to get column 'u_account' from result set.  Cause: java.sql.SQLDataException: Cannot determine value type from string '201577D0510'; Cannot determine value type from string '201577D0510'; nested exception is java.sql.SQLDataException: Cannot determine value type from string '201577D0510'    at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:84)    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)    at com.sun.proxy.$Proxy65.selectList(Unknown Source)

解决方法:

添加了entity子类中的无参构造方法,异常消失

java.sql.SQLException: Access denied for user ''@'localhost' (using password: NO)    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)    at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)    at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)    at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836)    at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456)    at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246)

解决方法:==时区报错==

更改配置信息:

spring:  datasource:    username: root    password: 123456    # 如果时区报错就需要添加 serverTimezone=UTC    url: jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8    driver-class-name: com.mysql.cj.jdbc.Driver

使用@Autowired注解有错误提示

  使用Spring boot +mybatis框架时,在service实现类中使用Mapper类,给Mapper类添加@Autowired注解时发现有错误提示:could not autowire,no beans of "XXX" type found,但程序的编译和运行都正常。处理方式:方案一:@Autowired(required = false)   设置required 属性值为 false,错误消失方案二:用@Resource注解替换@Autowired注解,错误消失@Resource注解与@Autowired注解的异同点这两个注解都是用作bean的注入时使用,都是为一个对象变量省去写get,set方法,自动为这个对象注入实例化对象(即注入依赖)注入的方式还是有所区别的 :@Autowired是基于spring的注解org.springframework.beans.factory.annotation.Autowired,它默认是按类型进行的装配的,如果想要它按名字进行装配则需在@autowired下面添加@qualifier("name")`注解,都无法找到唯一的一个实现类的时候报错。@Autowired注解默认情况下必须要求依赖对象必须存在,如果要允许null值,则应该设置它的required属性为false,@Resource 是基于j2ee的注解(可以减少了与spring的耦合),(JDK1.6以上支持)默认是按名字进行注解,若不指定装配bean的名字,当注解写在字段上时,默认取字段名,按照名称查找通过set方法进行装配,倘若有多个子类,则会报错。需要注意的是name属性一旦指定,就只会按照名称进行装配

解与@Autowired注解的异同点

这两个注解都是用作bean的注入时使用,都是为一个对象变量省去写get,set方法,自动为这个对象注入实例化对象(即注入依赖)注入的方式还是有所区别的 :

@Autowired是基于spring的注解org.springframework.beans.factory.annotation.Autowired,它默认是按类型进行的装配的,如果想要它按名字进行装配则需在@autowired下面添加@qualifier("name")`注解,都无法找到唯一的一个实现类的时候报错。@Autowired注解默认情况下必须要求依赖对象必须存在,如果要允许null值,则应该设置它的required属性为false,

@Resource 是基于j2ee的注解(可以减少了与spring的耦合),(JDK1.6以上支持)默认是按名字进行注解,若不指定装配bean的名字,当注解写在字段上时,默认取字段名,按照名称查找通过set方法进行装配,倘若有多个子类,则会报错。需要注意的是name属性一旦指定,就只会按照名称进行装配
``

The Ending

----------每天进步“亿”点点----------

-----Relyonyouself--