Mybatis-2-2.实操总结

通过上一部分的实操知道了Mybatis的用法。那么这章总结一下上一个实操项目。

实操项目全部源代码:
https://blacol.lanzouf.com/imBe303vouih
密码:wsfrg1

解决Loading class 'com.mysql.jdbc.Driver'. This is deprecated. The new driver class is 'com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.问题

在上一个实操项目中,每当执行一次测试方法都会出现这条内容。这虽然不是一个错误但是挺闹心的。之所以会有这句话是因为在mysql-connector-java-8这个版本有一套新的驱动来完成数据库的连接操作,这个驱动是com.mysql.cj.jdbc.Driver而错误语句的意思是“com.mysql.jdbc.Driver已经废弃,新的类是com.mysql.cj.jdbc.Driver。”要想解决这个问题在mybatis配置文件中将driver改成com.mysql.cj.jdbc.Driver即可。但是,新driver如果要连接mysql5则需要通过ssl来连接,如果不想通过ssl链接要在url后面添加参数useSSL=false。如果用的是8.0.27之前版本的驱动在连接数据库时还要指定时区。可以通过serverTimezone=Asia/Shanghai或者serverTimezone=GMT+8指定时区。

SqlSession的自动提交模式和手动提交模式。

在没有和任何框架整合之前SqlSession的提交事务的方式是手动的。这就是为什么实操中,在判断修改和添加是否成功的部分要加上session.commit()。(实操中删除操作因为没有提交所以即便删除成功数据库也没有变化。)
如果想要自动提交,在SqlSessionFactory的openSession方法中写如true参数就是自动提交的了。以实操的代码为例:

public class DBUtil {
        private static SqlSession session;
        private static void buildSqlSession() throws IOException {
            //单例SqlSession
            SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
            InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-cfg.xml");
            SqlSessionFactory build = builder.build(resourceAsStream);
            //session=build.openSession();
            session=build.openSession(true);//添加true后就会自动提交事务
        }
        public static SqlSession getSession() throws IOException {
            buildSqlSession();
            return session;
        }
    }

但是需要注意,自动提交往往是不可以回滚的,因为在sql语句执行完毕后mybatis就直接提交事务了,你根本没有时间回滚。除非执行语句时发生错误,那么mybatis会自动回滚。

Mapper接口方法返回值

Mapper中的方法的返回值一般有以下几种:

返回值类型 返回内容
void 什么都不返回
Object 查询到的内容
List/Set/Map 多条查询到的内容
boolean sql语句是否执行成功
int 影响了多少条数据

其中,Object、List/Set/Map是查询经常用到的类型。当sql返回的结果集只有1条,全都可以用,如果有多条那么Object就不能使用。比如:

  1. User selectUserById(String id),假设这个方法执行语句select * from user where id=#{id}(id为主键),那么是可以的。同样List selectUserById(String id)Set selectUserById(String id)也可以。返回值也可以是Map但是需要做一些工作,这里就不列出来了。后面会有一章讲解如何让sql语句返回map类型的结果。
  2. User selectUserByName(String name),假设这个方法执行语句select * from user where name=#{name}(name不是主键),如果只返回了一条数据那么是可以的,如果返回多条数据则不成功。

boolean和int在update、insert、delete中最为常见。
如果返回值是boolean,当插入、更新、删除成功时返回true(需要注意:影响多条数据也算作成功。),失败时返回false。
如果返回值是int,返回插入、更新、删除操作影响的数据条数。
当你只想删除一条数据并且不能保证用户真的只删除1条数据时使用int作为返回值是推荐的方案。(前提是session是手动提交的)

if(mapper.delete()==1){
  session.commit();//当只删除了1条数据则提交
}else{
  session.rollback();//当删除了多条数据则回滚
}

如果你只是判断用户操作是否成功而不关心用户是否操作了几条数据,那么int和boolean作为返回值都是推荐的(boolean不推荐用在删除数据的场合)。当返回值=0就代表执行不成功,返回值大于等于1则成功。

void返回值应用在全部的操作中。

Mapper方法参数问题

这个问题是最容易出现的。该问题往往出现在有2个及以上形参的方法参数有非基本数据类型的方法中。
如实操中的boolean updateProduct(String oldId,Product newProduct);方法,对于这种方法在编写配置文件时需要使用#{arg0},#{arg1},...占位。如果多个参数都是基本数据类型(包括String)使用arg0可能会报错。
如果不想使用arg0,arg1这种名称,可以在参数前面写上@Param注解。如刚才的方法可以变成下面的样子:
boolean updateProduct(@Param("oldId") String oldId,@Param("newProduct") Product newProduct);这个时候就可以使用#{newProduct.name}#{newProduct.price}#{oldId}占位了

Mapper映射文件特殊符号问题

在实操中编写Mapper映射文件时用><来替代>(大于)、<(小于)符号。因为在xml文件中>和<符号会被当做关键字。因此为了避免产生冲突使用实体符号><来代替。
><只能表示大于和小于,那么大于等于和小于等于怎么表示呢?
>=<=就可以。因为=不是特殊字符,xml是可以正常识别它的,>=会识别成>=,这不就是大于等于了吗。所以实操中的sql语句select * from Product where price < #{price}就会被识别成:

select * from Product where price < #{price}

Invalidate Binding(无效绑定)问题

有时在执行时会抛出这个错误。此时需要检查:

  1. target文件夹中是否有Mapper映射文件
  2. Mapper映射文件的名称、namespace是否和类名一致
  3. Mapper类是否有@Mapper注解
  4. select、update、insert、delete标签中的id值是否和Mapper类中的方法名一致
  5. Mybatis配置文件中Mapper的扫描路径是否正确。

对于1,在实操的部分已经有解决办法了。对于2~5自己仔细检查即可。

插入数据库的数据乱码

如果你的java文件的编码以及数据库的编码都是同一系列的字符编码则不会出现这个问题,如果不幸出现了,可以在连接数据库的url中加上字符集相关设置。如果你的java文件的编码不是同一系列的,你可以修改java文件编码(推荐)也可以修改数据库编码(不推荐)

英文数据查询时不区分大小写/英文排序结果不区分大小写

这与字符集的排序规则是否是i和s有关。i是不区分,s是区分ai是不区分注音(有些语言的字符上有注音符号),as是区分,ci是不区分大小写(a和A都看作是a),cs是区分大小写。实操当中使用的是utf8mb64_0900_ai_ci排序规则,这种排序规则并不会区分大小写,如果要区分大小写可以改成utf8mb64_0900_as_cs或者utf8mb64_0900_ai_cs都可以,如果不想改字符集还可以在where后添加BINARY关键字来让它区分大小写。

你可能感兴趣的:(Mybatis-2-2.实操总结)