mybatis 注解式 XML式 通用mapper(tk-mybatis)使用

Jdbcjpa、mybatis区别

1.Jdbc(java database connectivety)是java数据库连接规范,但由于其使用过于繁琐,出现了ORM(object relative mapping)对象关系映射对jdbc进行了封装,简化了操作,常见的ORM有mybatis、hibernate等

2.JPA(Java Persistence API) ,是Sun官方提出的一种ORM规范.为了简化现有Java EE和Java SE应用开发工作整合ORM技术,实现天下归一。Hibernate、Spring-data-jpa框架都是基于JPA规范一种实现。JPA提供了一套标准化API,使得开发者可以更方便地进行关系型数据库的操作,而无需关心具体的实现细节。

3.Mybatis是一种半自动化的数据访问框架,需要开发者手动编写SQL语句。Mybatis适合对SQL语句的细粒度控制和优化。

mybatis与jpa(Hibernate)区别:

Mybatis半自动的ORM框架,提供数据库与结果集的映射;需要自己去写SQL

JPA(Hibernate)是全自动的ORM框架,提供对象与数据库的映射;不需要我们写sql,支持数据库迁移自动建表

jpa移植性比较好,不用关心用什么数据库,因为mybatis自由写sql语句,所以当项目移植的时候还需要改sql。

mybatis需要手写sql,在sql中手动指定表名只需将实体类的属性和表中字段对应起来即可。

JPA、mybatis plus等需要明确指定实体类对应的数据表名称(消除了手动编写SQL语句的繁琐工作)。比如mybatis plus(@TableName(value = "tb_employee") 默认规则为TbEmployee => tb_employee)

1.Mybatis+注解式基础

mybatis插入mysql数据库中文编码异常

1、mysql数据库的表的编码不对,要用utf-8

2、项目编码不对,编码拦截器要配置utf-8

3、mybatis、jdbc工具的编码不对,在yml中mysql数据库url后面加上参数?useUnicode=true&characterEncoding=utf-8

useUnicode  是否使用Unicode字符集

characterEncoding     当useUnicode设置为true时,指定字符编码。比如可设置为utf-8 

1-1.@MapperScan("com.example.demo.Mapper")写在启动类上自动扫描Mapper接口包(接口与xml文件在同一包下时会自动加载xml文件)

1-2.或在接口类上添加@Mapper也能进行接口扫描,不用使用@MapperScan了。只不过与@MapperScan扫描接口的入口(使用的类)不一样。

2.@SpringBootApplication会默认扫描启动类所在目录以及子目录;如果需要扫描别的目录,需要加@ComponentScan;但是:3.@ComponentScan会覆盖@SpringBootApplication扫描的目录,所以,如果使用了@ComponentScan一定要把启动类目录也加上去。

mybatis半自动ORM框架(需要手写sql完成查询关联对象),在sql中手动指定表名只需将实体类的属性和表中字段对应起来即可。

而像jpa、mybatis plus等全自动ORM框需要明确指定实体类对应的数据表名称(消除了手动编写SQL语句的繁琐工作)。比如mybatis plus(@TableName(value = "tb_employee") 默认规则为TbEmployee => tb_employee)

Mybatis默认不开启驼峰规则若配置开启了驼峰规则,实体类属性名就不能再使用下划线命名了(sql语句中指定表名、列名),要使用驼峰命名否则会匹配不上数据库字段。因为mybatis会先将查询出来的数据库下划线列名进行驼峰转换。即 book_id 转化为bookId,再去和实体类属性名进行映射,此时实体类属性名仍为book_id即会出现匹配不上错误。解决办法可以配置resultMap映射,或实体类使用驼峰规则命名bookId。

Mybatis的application.yml标准示范:

spring:

  datasource:

    #   连接池类

      type: com.alibaba.druid.pool.DruidDataSource

      driver-class-name: com.mysql.jdbc.Driver

      platform: mysql

      url: jdbc:mysql://localhost:3306/task_control_center?useUnicode=true&characterEncoding=utf-8

      username: root

      password: toor

      filters: stat

      maxActive: 15

      initialSize: 1

      maxWait: 60000

      minIdle: 3

      timeBetweenEvictionRunsMillis: 60000

      minEvictableIdleTimeMillis: 300000

      validationQuery: select 'x'

      testWhileIdle: true

      testOnBorrow: false

      testOnReturn: false

      poolPreparedStatements: true

      maxOpenPreparedStatements: 20

# mybatis整合

mybatis:

# pojo类扫描

  type-aliases-package: com.dzj.arithmetic.demo.pojo

  configuration:

#驼峰命名规则开启。仅实体类属性名需使用驼峰命名

    mapUnderscoreToCamelCase: true

Mybatis的#{} 来进行模糊查询,like #{}  %+value+%不需要加单引号’) #{name}传参会自动添加单引号’’

利用sqlSession手写接口实现类:多个参数可借助map(只需key与xml中参数名一致的)、javaBean类、注解的方式(@Param String name与xml中参数名一致)   返回值有多个时:在Mapper接口用集合List<Bean>;会自动将Bean传到List集合中

注解式使用<if>标签判断传来的参数是否为空字符串或null

@Select("<script> " +
        "select * from algorithm where user_role_id!='-1'" +
        "<if test=\"algorithmName!=''\"> and name like #{algorithmName} </if>" +
        "<if test=\"algorithmType!=''\"> and algorithm_file_path = #{algorithmType} </if>" +
        "</script>")
List<Algorithm> listAlgorithm(@Param("algorithmName")String algorithmName,@Param("algorithmType")String algorithmType);

2.Xml式相关基础

ResultType=java.lang.Integer  不写ResultType是返回void

可以不写parameterType,因为mybatis能自动识别,但返回值类型(ResultType:java实体类名 或 ResultMap type=包名.类名:前面定义的resultMap的id)不能不写

Mybatis使用注意事项:

mapper.xml中parameterType可以不写会自动判断.   如使用@Param(“name”) String name的话,mybatis会自动判断将其作为parameterType=map来处理。直接int age则自动判断parameterType=java.lang.Integer处理。

Xml中namespace与接口名一致(包名.接口名),且<insert></insert>id与接口中方法名一致时,通过扫描xml与接口mybatis可以自动帮我们注册实现类到spring容器。

//sql语句中指定数据库表,resultMap中type字段指定实体类

<resultMap type="User" id="myresultmap"></resultMap>中设置数据库列名与Bean对象名的映射关系(以使通过Bean对象传参不会出错,同时往数据库增删改数据时不会出错)

<insert >insert into 表名(a) values(s)</insert>表名要与数据库的一致

sqlMapConfig中设置typealiys作用是写Bean类时不用再写包名

Mapper层中yonghuMapper接口

public interface yonghuMapper {

 List<yonghu> selectYonghuByIdUsedMap(@Param(“id”) String id);

 List<yonghu> selectYonghuById(@Param("id") String id);

 /*xml文件书写规范:1 namespace是接口的包名.接口名     2返回值类型是集合的话泛型与resiltType一样yonghu自动填充到List中。非集合的话:返回值类型与yonghuMapper.xml中resultType一样  

 3参数类型与parameterType中一样   4方法名与id一样*/

}

Mybatis逆向工程生成器自动生成的Mapper接口 中insert方法必须参数全部传入,insertSelective可以只传部分参数

IDEA中使用maven加载一个包下的Mapper接口与xml文件时出错(eclipse不会出问题)

报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

原因xml与接口映射出现问题。  也有可能是因为maven编译时src/main/java文件不保留配置文件有关。

解决:为了实现在maven默认环境下打包时,Mybatis的接口和mapper文件在同一包中,可以通过将接口文件放在src/main/java某个包中,而在src/main/resources目录中建立同样的包,这是一种约定优于配置的方式,这样在maven打包的时候就会将src/main/java和src/main/resources相同包下的文件合并到同一包中。

一对多查询(List属性链接):

<mapper namespace="Mapper.User_AddressMapper">

<resultMap type="User" id="myresultmap"> <!-- User实体 含三个属性 id、name、list(List<Address>) -->

<id property="id" column="id"/>

<result property="name" column="name"/> 

<collection property="list" javaType="list" ofType="Address"> <!-- Address实体包含俩属性 id、location collection标签主要作用就是做复杂数据List的配置。 对于int、string等类型数据直接用<result>即可-->

<id property="id" column="aid"/>

<result property="location" column="location"/>

</collection>

</resultMap>

<select id="select" resultType="User">

<select id="select" resultMap="myresultmap">  <!-- id、name、 aid、location    aid和location自动填到<collection>中-->

select user.id,user.name,address.id as aid,address.location from user,address where user.id=address.id

</select>

</mapper>

where标签(都不匹配则没有where。 只有一个匹配where a=?  多个匹配 where a=? and b=?)

<where>  

 <if test="state != null"> AND state = #{state} </if> 

 <if test="title != null">  AND title like #{title} </if> 

 </where>

Eclipse中Mapper接口和XML文件在一个包中时

只需配置mapper接口自动扫描即可

<!--mapper接口  mapper接口与xml文件在一个包下时会自动扫描mapper接口对应的xml文件,且Java接口的名称和mapper文件的名称要相同-->

 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

 <property name="basePackage" value="Mapper"></property></bean>

IDEA中Maven项目中maven打包工具时mybatis中可能出现的问题(eclipse不会出现问题):

在默认的情况下使用maven打包工具打包的时候,对于src/main/java目录只打包源代码,而不会打包其他文件。所以此时如果把对应的mapper文件放到src/main/java目录下时,不会打包到最终的jar文件夹中,运行出现问题 

  解决办法1、为了实现在maven默认环境下打包时,Mybatis的接口和mapper文件在同一包中,可以通过将接口文件放在src/main/java某个包中,而在src/main/resources目录中建立同样的包,这是一种约定优于配置的方式,这样在maven打包的时候就会将src/main/java和src/main/resources相同包下的文件合并到同一包中。推荐!!  (ps:可以使用maven打包,用解压工具看一看编译结构对不对)

办法2、如果不想将接口和mapper文件分别放到src/main/java和src/main/resources中,而是全部放到src/main/java,那么在构建的时候需要指定maven打包需要包括xml文件,具体配置如下:

<build> <resources> <!--mybatis  默认java目录下的xml在IDEA中编译时被拦截 无法输出出来-->
   <resource> <!配置成 允许java目录下xml和properties的输出-->
      <directory>src/main/java</directory>
      <includes>
         <include>**/*.xml</include>  <!--前面是什么文件夹都可以,只要是.xml结尾的都加入jar包。 只要是include打包时就一定会加入进去,只要是exclude就一定不会加入进去。 与true或者false无关。 -->
         <include>**/*.properties</include>
      </includes>
      <filtering>true</filtering>  <!--true为交给maven处理   false为不交给meven处理。-->
   </resource>

如果mapper.xml 放src/main/java而不是resources下,需要手动加 <resource>这个时候就覆盖了默认的<resource>得再把src/main/resources给加进来

   <resource> <!配置resouce  使用默认的允许全部输出(加入jar包)<includes><include>**/*.*</include></includes> -->
      <directory>src/main/resources</directory>
      <filtering>true</filtering>
   </resource>
</resources>

</build>

IDEA中Mapper接口和XML文件不在一个包中时mybatis扫描xml和接口自动生成接口实现类

ssm项目不能直接在IDEA中打开,springboot可以。

1、Springboot中分别扫描xml与接口文件:Application.yml中配置xml扫描

mybatis:

  type-aliases-package: com.example.demo.Bean

  mapper-locations: classpath:com/example/demo/Mapper/*.xml #扫描xml文件

    mapUnderscoreToCamelCase: true #开启驼峰规则  myUser会被对应到数据库字段my_user上

在主启动类上添加接口扫描:@MapperScan("com.example.demo.Mapper")写在启动类上自动扫描Mapper接口包(接口与xml文件在同一包下时会自动加载xml文件)

或在接口类上添加@Mapper也能进行接口扫描,不用使用@MapperScan了。只不过与@MapperScan扫描接口的入口(使用的类)不一样。

2、ssm配置方法一:配置mybatis配置文件

<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE configuration

  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

  "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

  <mappers>

    <mapper resource="mappers/UserMapper.xml"/>   <!-- 扫描指定mapper的xml文件,不能加classpath,也不能加* 。  需要注意的是这种方式配置的xml扫描会自动根据mapper.xml中的namespace加载接口  <mapper class="com.example.UserMapper"/>接口扫描主要用于ssm的注解式mybatis--> 

    <package name=" manage.mapper" />  <!-- 扫描包下的接口文件,xml与接口名一致时自动将xml也扫描 ,否则只扫描接口-->

  </mappers>

</configuration>

Or ssm方法二:配置Spring配置文件

<beans xmlns="http://www.springframework.org/schema/beans"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"

  xsi:schemaLocation="

  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

  http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">

 <!-- sqlSessionFactory -->

 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

 <property name="configLocation" value="classpath:sqlMapConfig.xml"></property>

 <property name="dataSource" ref="dataSource"></property>

  <!-- 配置mapper.xml文件位置,扫描映射文件,可以使用Ant风格的路径格式。此方法不会自动加载namespace对应接口 -->

    <property name="mapperLocations" value="classpath:mappers/**/*.xml" />

 </bean>

 <!—扫描mapper接口  mapper接口与xml文件在一个包下时会自动扫描mapper接口对应的xml文件生成接口实现类,否则只扫描接口-->

 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

 <property name="basePackage" value="Mapper"></property></bean>

</beans>

3.通用mapper (继承tk-mybatis Mapper)

类似mybatis plus,简化操作,避免重复写sql. 只需要简单继承 TKMybatis 提供的接口,即可使用crud方法。只是针对mapper接口层的简化(tk.mybatis.mapper.common.Mapper)且 其分页只能基于PageHelper插件, 代码生成器使用mybatis-generator。

1、需要引入tk-mybtis的pom

<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>RELEASE</version>
</dependency>

2.实体类

@Table ( name = "t_user" ) //手动映射表名与实体类名对应关系(默认规则为TUser => t_user)

public class User implements Serializable {

private static final long serialVersionUID = 1L ;

@Id

@GeneratedValue ( strategy = GenerationType.IDENTITY )

private Long id ;

@Column(name = “user_name”) //列名映射 默认驼峰转下划线形式

private String userName;

}

3.创建通用mapper接口且继承Mapper<T>类泛型

import tk.mybatis.mapper.common.Mapper;
public interface UserMapper extends Mapper<User> {
}

扫描mapper接口

主启动类配置:@MapperScan("com.example.demo.mapper")

4.使用从Mapper<User>继承来的相关方法

//定义通用Service类。   

public class ServiceBase<E> {

     /* 泛型注入  */

  @Autowired

  private Mapper<E> mapper;

    public List<E> select() {
        return
mapper.select(null);
    }
    public List<E> select(E y) {
        return
mapper.select(y);
    }
    public E find(Object id) {
        return
mapper.selectByPrimaryKey(id);
    }
    public E findEntity(E id)
    {
        return
mapper.selectOne(id);
    }
    public List<E> selectPage(E obj, int page, int pageSize) {
        PageHelper.startPage(page , pageSize , true);
        List<E> list = select(obj);
        return list;
    }
    public List<E> selectPageExample(Example obj , int page , int pageSize)
    {
        PageHelper.startPage(page , pageSize , true);
        List<E> list =
mapper.selectByExample(obj);
        return list;
    }
    public int delete(Object id)
    {
        return
mapper.deleteByPrimaryKey(id);
    }
    public int insert(E y) {
        return
mapper.insertSelective(y);
    }
    public int update(E y) {
        return
mapper.updateByPrimaryKeySelective(y);
    }
}

@Service("UserService")
public class UserServiceImpl extends ServiceBase<User> implements UserService {

}

5、controller层调用service:

@Autowired
private UserService service;

Example example = new Example(User.class); //  创建一个扩展搜索类
Example.Criteria criteria = example.createCriteria();

List<User> list = service.selectPageExample(example , page , 12); //基于PageHelper分页插件进行分页查询。配置详见下面第4部分。

4.MybatisPageHelper分页插件

原理:

PageHelper方法使用了静态的ThreadLocal参数,分页参数和线程是绑定的。内部流程是ThreadLocal中设置了分页参数(pageIndex,pageSize),之后在查询执行的时候,获取当线程中的分页参数,执行查询的时候通过拦截器在sql语句中添加分页参数,之后实现分页查询查询结束后在 finally 语句中清除ThreadLocal中的查询参数

  1. 引入依赖

        <dependency>

            <groupId>com.github.pagehelper</groupId>

            <artifactId>pagehelper-spring-boot-starter</artifactId>

            <version>1.2.10</version>

        </dependency>

  1. 编写配置类

import com.github.pagehelper.PageHelper;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration

public class PageHelperConfig {

    @Bean

    public PageHelper createPaeHelper(){

        PageHelper page= new PageHelper();

        return page;

    }

}

  1. 使用

  @RequestMapping("/index")

    @ResponseBody

    public Map<String, Object>  index(@RequestParam Map condition){

        System.out.println(condition);

// 接受前端传过来的,起始页,每页记录数这两个参数,将其转换为整数

        int startPage= Integer.parseInt((String)condition.get("page"));

        int pageSize= Integer.parseInt((String)condition.get("limit"));

//  创建Page对象,将page,limit参数传入,必须位于从数据库查询数据的语句之前,否则不生效

        Page page= PageHelper.startPage(startPage, pageSize);

//  ASC是根据id 正向排序,DESC是反向排序

        PageHelper.orderBy("id ASC");

// 从数据库查询,这里返回的的allUser就已经分页成功了(仅对mybatis查询有效)

        List<User> allUser = userService.getAllUser();

//用PageInfo对结果进行包装

//PageInfo pageinfo = new PageInfo(list);

//测试PageInfo全部属性PageInfo包含了非常全面的分页属性

pageinfo.getPageNum();pageinfo.getPageSize();pageinfo.getTotal();pageinfo.getFirstPage();

// 获取查询记录总数,必须位于从数据库查询数据的语句之后,否则不生效

        long total = page.getTotal();

// 下是layui的分页要求的信息

        HashMap<String, Object> map = new HashMap<>();

        map.put("code",0);

        map.put("msg","请求成功");

        map.put("data",allUser);

        map.put("count",total);

        return  map;

    }

报错及解决

ssm配的Mybatis运行报错:DruidPool getConnection TimeOut 大致就是从连接池里获取连接超时。

解决:手写了个driud连接池获取连接代码测试了一下发现报这个错Unknown system variable 'tx_isolation',说明mysql驱动包版本不对并且程序一直处于运行状态。然后将mysql jar包改为8.0.11后依然不管用。直接换成dbcp连接池后问题成功。

报错:java.sql.SQLException: validateConnection false 。 at com.alibaba.druid.pool.DruidAbstractDataSource.validateConnection

解决:版本问题,将druid依赖升级为1.1.10即可

报错:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'OPTION SQL_SELECT_LIMIT=DEFAULT' at line 1

原因:mybatis用的jdbc驱动版本mysql-connector-java-5.1.6.jar,mysql数据库版本为5.6.4,jdbc在连接数据库时候会发送测试语句SET OPTION SQL_SELECT_LIMIT=DEFAULT,这在mysql5.6以下版本是可以的 ,但是5.6不再支持SET,需要使用新的语句。

解决:升级驱动版本,我改成了mysql-connector-java-5.1.25.jar ,然后问题解决

discard long time none received connection. , jdbcUrl : jdbc:mysql://

原因:druid会从连接池取出连接判断连接是否超过60s没有使用,如果超过60s丢出如上的警告,再获取新的数据库连接返回。

1、连接超过60s未使用才会抛出这个报错,那么只要在60s内有进行数据库操作就行了,项目中加个定时任务每30s执行一次select 1

或者 2、在启动类增加:System.setProperty("druid.mysql.usePingMethod","false");

原理是让验证空闲连接不使用mysql的ping方法,而是使用select 1,这样每次进入上面提到的源码中时,时间都会刷新,就不会超过60s。

  • 23
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李庆政370

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值