栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Mybatis】Mybatis基础(中)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Mybatis】Mybatis基础(中)

目录

1、作用域(Scope)和生命周期

2、解决属性名和字段名不一致的问题

2.1、SQL别名

2.2、结果映射(resultMap)

3、日志

3.1、日志工厂

3.2、log4j

4、分页

4.1、Limit分页

4.2、RowBounds分页(了解即可)

4.3、分页插件(了解即可)

5、使用注解开发

5.1、操作实例

5.2、通过注解进行CRUD

5.3、@Param()注解

6、Mybatis基层运行

7、Lombok使用

7.1、简介

7.2、使用步骤

8、多对一处理

8.1、环境搭建

8.2、按查询嵌套处理

8.3、按结果嵌套处理

9、一对多处理

9.1、环境搭建

9.2、按查询嵌套处理

9.3、按结果嵌套处理

9.4、小结


1、作用域(Scope)和生命周期

不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题

SqlSessionFactoryBuilder:

  • 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。

  • 局部变量

SqlSessionFactory:

  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。

  • 相当于数据库连接池

  • 因此 SqlSessionFactory 的最佳作用域是应用作用域。最简单的就是使用单例模式或者静态单例模式。

SqlSession:

  • 连接到连接池的一个请求

  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。

  • 用完之后需要关闭,否则会资源占用

每一个mapper代表一个具体的业务(就是去执行SQL)。

2、解决属性名和字段名不一致的问题

数据库中的字段

User实体类

public class User {
    private int id;
    private String name;
    private String password;//字段不同
    ......}

结果

2.1、SQL别名

MyBatis 会在幕后自动创建一个 ResultMap,再根据属性名来映射列到 JavaBean 的属性上。如果列名和属性名不能匹配上,可以在 SELECt 语句中设置列别名(这是一个基本的 SQL 特性)来完成匹配.


    select * from mybatis.user

3、日志

3.1、日志工厂

在对数据库进行操作时,如果出现了异常,就需要排错,最好的方法就是看日志

Mybatis 通过使用内置的日志工厂提供日志功

能。内置日志工厂将会把日志工作委托给下面的实现之一:

  • SLF4J

  • Apache Commons Logging

  • Log4j 2

  • Log4j【掌握】

  • JDK logging

  • Commons_Logging

  • Stdout_Logging【掌握】

  • No_Logging

在mybatis具体使用哪一个日志实现,在设置中设定

Stdout_Logging:标准日志输出

注意:写settings的时候一定要注意在配置文件的位置,上面有讲到过。


    

下面我将select语句里面的*去除,看看日志文件怎么显示


    select * from mybatis.user

3.测试

//通过RowBounds进行分页查询
@Test
public void getUserByRowBounds(){
    SqlSession sqlSession = MybatisUtils.getsqlSession();
    //RowBounds实现
    RowBounds rowBounds = new RowBounds(1, 2);
    //通过Java代码层实现分页
    List userList = sqlSession.selectList("com.wen.Dao.UserMapper.getUserByRowBounds", null, rowBounds);
    for (User user : userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

4.结果

4.3、分页插件(了解即可)

分页插件自己写的小项目可以不用写,写SQL还可以练练手,但以后写大项目的时候可能会用到这个,详情请看:MyBatis 分页插件 PageHelper,分页插件 | MyBatis-Plus

5、使用注解开发

对于像 BlogMapper 这样的映射器类来说,还有另一种方法来完成语句映射。 它们映射的语句可以不用 XML 来配置,而可以使用 Java 注解来配置。比如,上面的 XML 示例可以被替换成如下的配置:

package org.mybatis.example;
public interface BlogMapper {
    @Select("SELECT * FROM blog WHERe id = #{id}")
    Blog selectBlog(int id);
}

使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

选择何种方式来配置映射,以及认为是否应该要统一映射语句定义的形式,完全取决于你和你的团队。 换句话说,永远不要拘泥于一种方式,你可以很轻松的在基于注解和 XML 的语句映射方式间自由移植和切换。

5.1、操作实例

实例:

1、在接口上使用注解

//查询全部用户
@Select("select * from user")
List getUserList();

2、在mybatis-config.xml配置文件中绑定接口


    

3、测试

@Test
public void test(){
    SqlSession sqlSession = MybatisUtils.getsqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List userList = mapper.getUserList();
    for (User user : userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

4、结果

本质:反射机制实现

底层:动态代理(在Spring中讲到过)

5.2、通过注解进行CRUD

由于操作雷同,所以接口上写上所有操作,但运行只运行一个增加操作即可

接口:

//查询全部用户
@Select("select * from user")
List getUserList();
​
//方法存在多个参数时,所有的参数前面都必须加上@Param("id")注解
@Select("select * from user where id = #{id}")
User getUserByID(int id);
​
//配置文件取参数的时候取的是@Param()里的参数!!!
@Select("select * from user where id = #{id} and pwd = #{pwd}")
User getUser(@Param("id") int id,@Param("pwd") String pwd);
​
//添加,对象就不用加@Param()
@Insert("insert into user(id,name,pwd) values(#{id},#{name},#{pwd})")
int addUser(User user);
​
//删除
@Delete("delete from user where id = #{id}")
int deleteUserByID(int id);
​
//修改
@Update("update user set name = #{username},pwd = #{userpwd} where id = #{userid}")
int updateUser(User user);

测试:

public class UserDaoTest {
    @Test
    public void test(){
        SqlSession sqlSession = MybatisUtils.getsqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        int user = mapper.addUser(new User(4, "老四", "456"));
        List userList = mapper.getUserList();
        for (User user1 : userList) {
            System.out.println(user1);
        }
        sqlSession.close();
    }
}

注意:我们在使用修改语句的时候需要提交事务: sqlSession.commit();

但可以在MybatisUtils工具类里的getsqlSession()方法中,提交事务为true,使其自动提交事务。

//有了sqlSessionFactory就可以获取sqlSession的实例
//sqlSession完全包含了面向数据库执行SQL命令所需的方法
public static SqlSession getsqlSession(){
    return sqlSessionFactory.openSession(true);
}

结果:

5.3、@Param()注解
  • 多个基本类型的参数或者String类型需要加上

  • 引用类型不需要添加

  • 只有一个基本类型,可以忽略,建议加上

  • 在SQL中传入的值是@Param()内的值

6、Mybatis基层运行

通过debug查看操作流程

7、Lombok使用

7.1、简介

Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,可以通过简单的注解的形式来帮助我们简化和消除一些必须有但显得很臃肿的Java代码,比如常见的Getter and Setter、构造函数、toString()等等。用来消除Java类中的大量样板代码,简洁且易于维护的Java类。

常用注解:

@Setter :注解在类或字段,注解在类时为所有字段生成setter方法,注解在字段上时只为该字段生成setter方法。
@Getter :使用方法同上,区别在于生成的是getter方法。
@ToString :注解在类,添加toString方法。
@EqualsAndHashCode: 注解在类,生成hashCode和equals方法。
@NoArgsConstructor: 注解在类,生成无参的构造方法。
@RequiredArgsConstructor: 注解在类,为类中需要特殊处理的字段生成构造方法,比如final和被@NonNull注解的字段。
@AllArgsConstructor: 注解在类,生成包含类中所有字段的构造方法。
@Data: 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。
@Slf4j: 注解在类,生成log变量,严格意义来说是常量。

7.2、使用步骤

1.在IDEA中安装Lombok插件

File --> Settings --> Plugins -->搜索lombok -->下载即可

2.在项目中导入lombok的jar包

在maven项目的pom.xml内写入lombok的依赖


    org.projectlombok
    lombok
    1.18.10

注意:记得看一下有没有加载进去

3.使用注解

  • @Data: 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法。

  • @AllArgsConstructor: 注解在类,生成包含类中所有字段的构造方法。

  • @NoArgsConstructor: 注解在类,生成无参的构造方法。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
​
}

查看方法:

8、多对一处理

本次实验以书和书籍类作比方

  • 对书而言,多本同类型的书籍关联一个类型,如计算机类【多对一】

  • 对书籍类型而言,一个计算机类型集合了很多本计算机书籍【一对多】

首先,创建数据库,本次要做的便是联表查询:

创建书本类型和书的表:

类型表:
CREATE TABLE `type` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
​
图书表:
CREATE TABLE `book` (
  `id` int(11) NOT NULL,
  `name` varchar(255) DEFAULT NULL,
  `tid` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `tid` (`tid`),
  ConSTRAINT `tid` FOREIGN KEY (`tid`) REFERENCES `type` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

8.1、环境搭建

1.新建实体类Book,BookType

由于之前讲到了lombok,所以这里我们使用它,主要是方便。

@Data
public class Book {
    private int id;
    private String name;
    //书本要关联一个类型,所以需要一个对象:每个书本都对应一个对象
    private BookType tid;
}
@Data
public class BookType {
    private int id;
    private String name;
}

2.建立Mapper接口

先测试一下环境,先通过id来查询一本书,这里用的是注解来实现查询

public interface BookMapper {
    @Select("select * from book where id = #{id}")
    Book getBook(@Param("id") int id);
}
public interface BookTypeMapper {
}

3.建立Mapper.xml

为了美观Mapper.xml建议建在resource下,注意:包名尽量相同

4.在mybatis-config.xml中注册Mapper.xml


    
    

5.测试

@Test
public void test(){
    SqlSession sqlSession = MybatisUtils.getsqlSession();
    BookMapper mapper = sqlSession.getMapper(BookMapper.class);
    Book book = mapper.getBook(1);
    System.out.println(book);
    sqlSession.close();
}

6.结果

7.项目结构

注意:记得检查你的*Mapper.xml有没有成功录入你的classes文件中,要不然找不到的。

8.2、按查询嵌套处理

目标:查询所有书本信息以及与其相对应的书本类型

select b.id,b.name,t.name from book b,type t where b.id = t.id;

思路:接口方法- -> 对应的mapper.xml方法 --->test

查询方法解析:

首先写了两个查询语句,第一个select * from book 是查询书本信息的,现在我们需要通过书本的tid来查该书本所属类别,所以需要再写一个select * from where id = #{tid}的查询语句从type里查询出来,然后通过resultMap的方式将数据整合在一起。

1.接口

public List getBookList();

2.*Mapper.xml里添加查询方法

注意:在resultMap中,复杂的属性不用result

  • 对象 ---> association

  • 集合 ---> collection

  • JavaType ---> 指定属性的类型

  • ofType ---> 集合中泛型信息

后续会涉及到的。


    
    
        select * from book
    
​
    
    
        
        
        
        
    
​
    
        select * from type
    

4.测试是否能查询出来

@Test
public void getBookList(){
    SqlSession sqlSession = MybatisUtils.getsqlSession();
    BookTypeMapper mapper = sqlSession.getMapper(BookTypeMapper.class);
    List books = mapper.getBooks();
    for (BookType book : books) {
        System.out.println(book);
    }
    sqlSession.close();
}

5.结果

可以看到后面的书籍为空,所以就要开始联表查询了

9.2、按查询嵌套处理

目的:获取指定书籍类下的所有书籍信息

select t.id,t.name,b.name from book b,type t where t.id = b.tid and t.id = 1 ;

思路:接口方法- -> 对应的mapper.xml方法 --->test

1.创建Mapperd 的获取方法

//获取指定书籍类下的所有书籍信息
BookType getBookType(int id);

2.在相应的mapper.xml里添加对应的查询语句


    select * from type where id = #{id}

    
    

    select t.id tid,t.name tname,b.name bname
    from book b,type t
    where t.id = b.tid and t.id = 1

​

    
    
    
    
        
        
    

3.测试

@Test
public void getBookType(){
    SqlSession sqlSession = MybatisUtils.getsqlSession();
    BookTypeMapper mapper = sqlSession.getMapper(BookTypeMapper.class);
    BookType bookType = mapper.getBookType(1);
    System.out.println(bookType);
    sqlSession.close();
}

4.结果

9.4、小结
  • 关联(对象)---->association---->多对一

  • 集合---->collection---->一对多

  • JavaType ---> 指定属性的类型

  • ofType ---> 集合中泛型信息,用来指定映射到List或集合中的pojo(实体类)类型,是泛型中的约束----->List---->Book

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/530458.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号