ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SSM---Mybatis

2021-11-05 03:00:22  阅读:128  来源: 互联网

标签:--- name mapper log4j SSM public user Mybatis id


Mybatis基础教程

一、简介

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

需要使用到的jar包:

  • mysql-connector-java.jar
  • mybatis.jar

注:如果使用maven创建项目的化,可以取maven仓库找到对应的mybatis包,再导入xml就好。

1、持久化的简介

数据持久化:

  • 持久化就是将程序的数据在持久状态和瞬时状态转化的过程
  • 内存:断电即失
  • 数据库(Jdbc),io文件持久化。

持久层:

例如:DAO层、Service层、Controller层

  • 完成持久化工作的代码块
  • 底层界限十分明显

2、Mybatis的特点

  • 方便写入数据到数据库中。
  • 不需要再写传统的JDBC代码,简化了代码,自动化。
  • sql和代码分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射。
  • 提供对象关系映射标签,支持对象关系组建维护。
  • 提供xml标签,支持编写动态sql

二、创建一个简单的Mybaits程序

在此之前需要新建一个数据库数据;

CREATE DATABASE `mybatis`;

USE `mybatis`;

CREATE TABLE `user`(
  `id` INT(20) NOT NULL PRIMARY KEY,
  `name` VARCHAR(30) DEFAULT NULL,
  `pwd` VARCHAR(30) DEFAULT NULL
)ENGINE=INNODB DEFAULT CHARSET=utf8;

--自行插入数据到数据表中;

接下来创建一个项目,导入所需要的所有Jar包,然后就可以编写代码了;

创建一个database.properties,用来定义JDBC数据连接数据库:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql:/本机地址:3306/数据库?useUnicode=true&characterEncoding=utf-8&useSSL=true
username=数据库账号
password=密码

最重要的一点,编写mybaits-config.xml核心配置:

(可以查看Mybatis开发文档:https://mybatis.org/mybatis-3/zh/index.html)

<?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核心配置文件-->
<configuration>
    <!--  获取配置文件database.properties  -->
    <properties resource="database.properties"></properties>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--  每一个Mapper.xml都需要在Mybatis核心配置中注册!  -->
    <mappers>
        <mapper resource="com/vxzx/dao/UserMapper.xml"></mapper>
    </mappers>
</configuration>

可以再编写一个获取Mybatis的Sqlsession的工具类:

package com.vxzx.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;

//该配置是固定的:
public class MybatisUtils {
    //获取SqlSessionFactory对象:
    public static SqlSession getsqlSession(){
        SqlSession session = null;
        String resource = "mybaits-config.xml";
        try {
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            session = sessionFactory.openSession();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return session;
    }
}
  • pojo层的User类:
package com.vxzx.pojo;

public class User {
    private Integer id;
    private String name;
    private String pwd;

    public User() {
    }

    public User(Integer id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "User{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", pwd='" + pwd + '\'' +
            '}';
    }
}
  • UserMapper接口:
package com.vxzx.dao;
import com.vxzx.pojo.User;
import java.util.List;
import java.util.Map;

public interface UserMapper {
    //获取所有用户信息:
    List<User> getUserList();
    //添加一个用户:
    int addUser(User user);
    //使用map修改用户:
    int updateUser2(Map<String,Object> map);
    //模糊查询:
    List<User> getUserByLike(String value);
}
  • UserMapper.xml (在这里面类似于编写以前的JDBC查询代码:)
<?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接口 -->
<mapper namespace="com.vxzx.dao.UserMapper">
    <!-- select:查询语句;  id:对应引用的方法名;resultType:返回结果集 -->
    <select id="getUserList" resultType="com.vxzx.pojo.User">
        select * from user
    </select>
    -- 只能修改pwd的数据,不能修改其他的数据:
    <insert id="addUser" parameterType="com.vxzx.pojo.User">
        insert into user(id,name,pwd) values(#{id},#{name},#{pwd})
    </insert>

    <update id="updateUser2" parameterType="map">
        update user set name=#{username},pwd=#{password} where id=#{id}
    </update>
    <select id="getUserByLike" resultType="com.vxzx.pojo.User">
        select * from user where name like #{value}
    </select>
</mapper>
  • UserMapperTest测试类:
//查询所有用户信息:
public void getUserList(){
    //1、获取SqlSession对象:
    SqlSession session = MybatisUtils.getsqlSession();
    //2、执行SQL: ----方式一:推荐使用
    UserMapper mapper = session.getMapper(UserMapper.class);
    List<User> userList = mapper.getUserList();
    //2、执行SQL: ----方式二:
    //        List<User> userList = session.selectList("com.vxzx.dao.UserMapper.getUserList");
    for (User user : userList) {
        System.out.println(user);
    }
    session.close();
}
//添加用户:
public void addUser(){
    SqlSession session = MybatisUtils.getsqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    int user1 = mapper.addUser(new User(5, "vxzx", "123"));
    if (user1 > 0){
        System.out.println("添加成功!");
    }
    //提交事务:必须执行,不然添加不进去
    session.commit();
    session.close();
}
//使用map修改用户:
public void updateUser(){
    SqlSession session = MybatisUtils.getsqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    Map<String,Object> map = new HashMap<String, Object>();
    //格式:(sql语句中的#{}的值,新的值);可以插入一个或多个,不用全部插入
    map.put("username","vx");
    map.put("password","111111");
    map.put("id",4);
    mapper.updateUser2(map);
    session.commit();
    session.close();
}
//模糊查询:
public void getUserByLike(){
    SqlSession session = MybatisUtils.getsqlSession();
    UserMapper mapper = session.getMapper(UserMapper.class);
    List<User> userList = mapper.getUserByLike("%x%");
    for (User user : userList) {
        System.out.println(user);
    }
    session.close();
}

如果出现配置文件无法导出或者生效的问题,可以在项目对应的pom.xml插入以下配置代码:

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>

三、Mybatis的CRUD

接下来,我们可以对上面代码进行详细的解析:

1、namespace

namespace中的包名要和 Dao/mapper 接口的包名一致!

2、select

选择,查询语句;

  • id : 就是对应的namespace中的方法名;
  • resultType:Sql语句执行的返回值!
  • parameterType : 参数类型!

2.1 编写接口

//根据ID查询用户
User getUserById(int id);

2.2 编写对应的mapper的sql语句

<select id="getUserById" parameterType="int" resultType="com.kuang.pojo.User">
    select * from mybatis.user where id = #{id}
</select>

2.3 测试

public void getUserById() {
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    User user = mapper.getUserById(1);
    System.out.println(user);
    sqlSession.close();
}

3、Insert

3.1 编写对应的mapper的sql语句

<!--对象中的属性,可以直接取出来-->
<insert id="addUser" parameterType="com.kuang.pojo.User">
    insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
</insert>

4、update

4.1 编写对应的mapper的sql语句

<update id="updateUser" parameterType="com.kuang.pojo.User">
    update mybatis.user set name=#{name},pwd=#{pwd}  where id = #{id} ;
</update>

5、delete

5.1 编写对应的mapper的sql语句

<delete id="deleteUser" parameterType="int">
    delete from mybatis.user where id = #{id};
</delete>

注意:增删改需要使用commit()提交事务;

6、使用map来定义数据中的数据

假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用Map!

6.1 编写代码

  • 编写接口类:
//万能的Map
int updateUser(Map<String,Object> map);
  • 编写对应的mapper的sql语句
<update id="updateUser2" parameterType="map">
    update user set name=#{username},pwd=#{password} where id=#{id}
</update>
  • 编写测试类:
public void updateUser(){
SqlSession session = MybatisUtils.getsqlSession();
UserMapper mapper = session.getMapper(UserMapper.class);
Map<String,Object> map = new HashMap<String, Object>();
    //格式:(sql语句中的#{}的值,新的值);可以插入一个或多个,不用全部插入
    map.put("username","vx");
    map.put("password","111111");
    map.put("id",4);
    mapper.updateUser2(map);
    session.commit();
    session.close();
    }

6.2 注意点

Map传递参数,直接在sql中取出key即可! 【parameterType="map"】

对象传递参数,直接在sql中取对象的属性即可!【parameterType="Object"】

只有一个基本类型参数的情况下,可以直接在sql中取到!

多个参数用Map,或者注解!

7、Mybatis的模糊查询

7.1 Java代码执行的时候,传递通配符 % %

对应的mapper的sql语句:

<select id="getUserByLike" resultType="com.vxzx.pojo.User">
    select * from user where name like #{value}
</select>

测试类中获取数据:

List<User> userList = mapper.getUserLike("%李%");	//加上通配符 % %

7.2 在sql拼接中使用通配符% %

一:对应的mapper的sql语句:

<select id="getUserByLike" resultType="com.vxzx.pojo.User">
    select * from user where name like "%"#{value}"%"
</select>

测试类中获取数据:

List<User> userList = mapper.getUserLike("李");		//在mapper中已加通配符,这里不用加了

四、Mybatis配置详解

核心配置文件:

  • configuration(配置)
  • properties(属性)
  • settings(设置)
  • typeAliases(类型别名)
  • typeHandlers(类型处理器)
  • objectFactory(对象工厂)
  • plugins(插件)
  • environments(环境配置)
  • environment(环境变量)
  • transactionManager(事务管理器)一般都为JDBC
  • dataSource(数据源)一般都为POOLED,配置连接数据的数据源
  • databaseIdProvider(数据库厂商标识)
  • mappers(映射器)

注意:各种配置必须严格按照其固定的顺序来使用。

1、 配置之属性

(1)属性(properties)

使用properties来引用外部数据源;例如:引入JBDC数据库连接;【database.properties】

这些属性都是可外部配置且可动态替换的,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来传递。

database.properties:

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=true
username=root
password=123456

在核心配置中直接引入:

<properties resource="database.properties"/>

在核心配置中添加一些配置:

<properties resource="db.properties">
    <property name="username" value="root"/>
    <property name="pwd" value="11111"/>
</properties>

注意:如果两个文件有同一个字段,那么会优先使用外部的配置信息。

(2)环境配置(environments)

Mybatis可以配置多种环境来使用;但是每个SqlSessionFactory实例只能使用一种配置。

其中,Mybatis默认的transactionManager一般为JDBC,dataSource为POOLED连接池。

  • default:环境配置默认选择的配置;
  • id:每个配置的标志,用以来区分各个配置;
<environments default="environment">
    <environment id="environment">
        <transactionManager type="JDBC"></transactionManager>
        <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
        </dataSource>
    </environment>
</environments>

2、 配置之别名

(1)设置(settings)

MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。

例如:配置日志文件实现;

<settings>
    <setting name="logImpl" value="log4j"/>
</settings>

(2)类型别名(typeAliases)

  • 别名的存在是为java类型设置一个简短的名字;
  • 可以减少类完全限定名的冗余;

使用设置别名,别名的使用:为该包下面的类首字母小写的类名字。

<typeAliases>
    <package name="com.vxzx.pojo"/>
</typeAliases>

使用设置别名,别名的使用:为alias后面的名字。

其中type为需要设置的类,alias为设置的别名。

<typeAlias type="com.vxzx.pojo.User" alias="user"></typeAlias>

后还想自己定义别名,可以使用注解来设置别名:

@Alias("user")
pubic class user(){}

3、 配置之映射器

  • MapperRegistry:注册绑定我们的Mapper文件
  • 配置对应的mapper映射文件 .xml
  • 每一个Mapper.XML都需要在Mybatis核心配置文件中注册

我们有三种方法可以使用:

一:常用(无其他注意点)

<mappers>
    <mapper resource="com/kuang/dao/UserMapper.xml"/>
</mappers>

二:使用class文件绑定注册

<mappers>
    <mapper class="com.kuang.dao.UserMapper"/>
</mappers>

注意:

  • 接口与其对应的Mapper配置必须同名
  • 接口与其对应的Mapper配置必须在听一个包下面

三:使用扫描包的方式注册绑定

<mappers>
    <package name="com.kuang.dao"/>
</mappers>

注意:

  • 接口与其对应的Mapper配置必须同名
  • 接口与其对应的Mapper配置必须在听一个包下面

4、 生命周期与作用域

image-20210719024632485

它的过程可以简单的理解为:创建sql工厂,打开sqlSession,使用Mapper来操作CRUD;

SqlSessionFactoryBuilder

  • 用来创建SqlSessionFactory,一旦创建完成,SqlSessionFactoryBuilder将被销毁。
  • 可以设置为局部变量,因为只需要使用一次。

SqlSessionFactory

  • 一旦创建,SqlSessionFactory 将会存在于您的应用程序整个运行生命周期中。
  • 因此 SqlSessionFactory 的最佳作用域是应用作用域。
  • 最简单的就是使用单例模式或者静态单例模式。

SqlSession

  • 连接到连接池的一个请求!
  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
  • 每个SqlSession里面可以有多个mapper业务。
  • 用完之后需要赶紧关闭,否则资源被占用!

5、 属性名与字段名不一致

实体类的属性名:

private Integer id;
private String name;
private String password;

数据库的字段名:

 id int(3) ;
 name varchar(10) ;
 pwd varchar(20) ;

其中,password与pwd就有区别。这样查询数据会查询出null。

解决方法一:直接在查询语句中设置别名as

<select id="getUserList" resultMap="resultmap">
    select id,name,pwd as password from user
</select>

解决方法二:使用resultMap结果映射

  • id:查询语句使用的resultMap名字;
  • type:映射的结果集类;
  • property:类中的属性名;
  • column:数据库中的字段名;
<resultMap id="resultmap" type="user">
    <!-- property:属性名; column:数据库字段名; -->
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <result property="password" column="pwd"/>
</resultMap>

<select id="getUserList" resultMap="resultmap">
    select * from user
</select>

对于简单的语句根本不需要配置显式的结果映射,而对于复杂一点的语句只需要描述它们的关系就行了。

你已经对它相当了解了,就不需要显式地用到他们。

6、实现分页

(1)使用limit分页

使用limit分页跟在sql里面的使用步骤一样,不同的是,需要在xml中填加该语句。

<!--  将查询出来的结果从1开始,每页展示三个  -->
<select id="getUserlistLmit"  resultType="user">
    select * from mybatis.user limit 0,3;	
</select>

(2)使用RowBounds分页

Mybatis提供了一个简单的逻辑分页使用类RowBounds。

首先,第一步先实例化一个RowBounds对象,里面输入的值为数据(起始值,显示页面值)

public RowBounds(int offset, int limit)

然后使用SQLsession中的selectList方法:

List<User> userList = sqlSession.selectList("com.vxzx.dao.UserMapper.getUserList", null, rs);
//传入的值:(需要查询的类的接口--及里面的方法,Object,RowBounds)
public void getUserListRow(){
    //实现从第一开始,每页显示2条数据的显示;
    RowBounds rs = new RowBounds(0,2);
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    //注意,要使用selectList的方法;
    List<User> userList = sqlSession.selectList("com.vxzx.dao.UserMapper.getUserList", null, rs);
    for (User user : userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

了解一些分页插件: PageHelper

五、日志

1、 日志工厂

数据库操作出现问题,就可以使用日志文件来进行排错。

Mybatis中日志的具体实现,可以在settings(设置)中设置。

在Mybatis核心配置文件中配置:

<settings>
    <setting name="logImpl" value="log4j"/>
</settings>

还可以自己设置日志数据输出格式和路径:(log4j.properties)

2、Log4j

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件;过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程;通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

具体使用步骤:

(1)导入log4j的jar包:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

(2)log4j.properties:

#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file

#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n

#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/vx.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n

#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

(3)配置log4j的实现:

<settings>
    <setting name="logImpl" value=""/>
</settings>

实际使用操作:

  • 在要使用log4j的类中,导入包 org.apache.log4j.Logger;
  • 日志对象,参数为当前类的class
import org.apache.log4j.Logger;

static Logger logger = Logger.getLogger(UserMapperTest.class);
  • 日志级别:
logger.info("输出的logger--->info");
logger.debug("输出的logger--->debug");
logger.error("输出的logger--->error");

3、扩展:使用注解开发

sql数据库的CURD我们都可以使用注解来进行简单的操作;

  • 查询:
@Select("select * from user where id=#{uid}")
User getId(@Param("uid")int id);
  • 添加:
@Insert("insert into user(id,name,pwd) values(#{id},#{name},#{password})")
int insertUser(User user);
  • 修改
@Update("update user set name=#{name} where id=#{id}")
int updateUser(User user);
  • 删除
@Delete("delete from user where id=#{uid}")
int deleteUser(@Param("uid")int id);

值得注意的一点是,需要在核心配置文件中绑定接口!

<!-- 使用注解方法=====绑定接口: -->
<mappers>
    <mapper class="com.vxzx.dao.UserMapper"></mapper>
</mappers>

4、Lombok

Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。

使用步骤:

  • 导入jar包;也可以添加maven依赖:
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>
  • 然后,在我们需要使用的实体类上面,添加上@Data
//导入lombok的jar包,使用Lombok注解,完成getter、setter
@Data               //etter、setter
@AllArgsConstructor     //有参构造
@NoArgsConstructor      //无参构造
@EqualsAndHashCode		//hashcode比较
@ToString
public class User {
    private Integer id;
    private String name;
    private String password;

}

六、SQL多数据处理

1、多对一处理

例如:多个学生对应一个老师的例子。

  • 对于学生来说,多个学生关联一个老师;----对象association
  • 对于老师来说,一个老师有很多学生;----集合collection
多对一查询:使用<resultMap>中的association;
    具体实现一:根据结果集映射查询
               先使用sql连表查询语句===>映射为resultMap;
               再使用resultMap,配置查询的数据的别名的问题,其中需要使用association,
               再在association里面配置数据库列信息;
    具体实现二:嵌套查询:
               先使用sql语句查询第一个表中的数据===>映射为resultMap;
               再使用resultMap,配置查询的第一个表;其中需要使用到association,
               注意的是,association里面不必在写查询语句了,只需要在标签处配置
               需要查询的第二个表的信息;
               接着,再查询第二表的信息,要与上面的resultMap进行配对。

对于这种问题,我们有两种方法:

实体类:

public class Student {
    private Integer id;
    private String name;
    private Teacher teacher;
}

接口类:

public List<Student> getStudent();
public List<Student> getStudent2();

第一种:根据查询嵌套处理

<!-- 多对一   方式一:-->
<select id="getStudent" resultMap="st">
    select * from student
</select>
<!--  复杂的属性需要:association->对象; collection->集合      -->
<resultMap id="st" type="student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="teacher">
    select * from teacher where id=#{tid}
</select>

第二种:按结果查询嵌套

<select id="getStudent2" resultMap="st2">
    select student.id as sid,student.name as sname,teacher.name as tname
    from student,teacher
    where student.tid = teacher.id
</select>
<resultMap id="st2" type="student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>

2、一对多处理

例如:一个老师对应多个学生;

  一对多查询:使用<resultMap>中的collection;
    具体实现一:根据结果集映射查询
                先使用sql连表查询语句===>映射为resultMapp;
                在使用resultMap,配置查询语句的数据的别名问题,其中需要使用到collection;
                再在collection中配置查询数据库列的信息;
                注意的是:
                    相较于association,还需要多配置实体类中对应的
                    ofType(集合中获取泛型信息);
    具体实现二:嵌套查询:
               先使用sql语句查询第一个表中的数据===>映射为resultMap;
               在使用resultMap,配置查询的第一个表;其中是要到的collection;
               注意的是,collection里面不必在写查询语句了,只需要在标签处配置;
               注意的是:
                        相较于association,还需要多配置实体类中对应的
                        javaType(指定属性的类型),ofType(集合中获取泛型信息);
               最后,再进行查询第二个表,要与上面的resultMap进行配对;

对于这种问题,我们有两种方法:

实体类:

public class Student {
    private Integer id;
    private String name;
    private  Integer tid;
}
public class Teacher {
    private Integer id;
    private String name;
    List<Student> students;
}

接口类:

List<Teacher> getTeacher(@Param("tid") int id);
List<Teacher> getTeacher2(@Param("tid") int id);

第一种:根据查询嵌套处理

<!--  collection 方式一:  -->
<select id="getTeacher" resultMap="ts">
    select * from teacher where id = #{tid}
</select>
<resultMap id="ts" type="teacher">
    <collection property="students" javaType="ArrayList"
                ofType="Student" column="id" select="getstudent">
    </collection>
</resultMap>
<select id="getstudent" resultType="student">
    select * from mybatis.student where tid = #{tid};
</select>

第二种:按结果查询嵌套

<!--  collection 方式二:  -->
<select id="getTeacher2" resultMap="ts2">
    select s.id as sid,s.name as sname,t.name as tname,t.id as tid
    from student as s,teacher as t
    where s.tid = t.id and t.id = #{tid};
</select>
<resultMap id="ts2" type="teacher">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <!--  javaType="" 指定属性的类型!
      集合中获取泛型信息,需要使用ofType获取
      -->
    <collection property="students" ofType="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <result property="tid" column="tid"/>
    </collection>
</resultMap>

3、总结

  • 关联-----association【多对一】
  • 集合-----collection【一对多】
  • javaType 与 ofType
    • javaType用来指定实体类中属性的类型
    • ofType用来指定映射到List或集合中的pojo的类型,泛型中的约束类型

七、动态SQL

动态 SQL 是 MyBatis 的强大特性之一。借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

简单来说,动态SQL就是指根据不同的条件生成不同的SQL语句。

  • if
  • choose(when,otherwise)
  • trim(where,set)
  • foreach

1、if

接口编写:

//动态sql:if
public List<Blog> getBlogm(Map<String,String> map);

mapper配置编写:

<!-- 动态 SQL·if: -->
<select id="getBlogm" resultType="blog" parameterType="map">
    select * from mybatis.blog
    <where>
        <if test="title != null">
            and title = "blog1"
        </if>
        <if test="author != null">
            and author = "zx"
        </if>
    </where>
</select>

测试编写:

    public void getBlogm(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap<String,String> map = new HashMap();
      	map.put("title","blog1");

        List<Blog> blogm = mapper.getBlogm(map);
        System.out.println(blogm);
        sqlSession.close();
    }

2、choose (when, otherwise)

  • 相当于SQL语句中的条件筛选语句

其中接口类,测试类的配置基本都是一样的。

<!-- choose (when, otherwise):   -->
<select id="getBlogmChoose" resultType="blog" parameterType="map">
    select * from mybatis.blog
    <where>
        <choose>
            <when test=" title != null">
                and title = "title1"
            </when>
            <otherwise>
                and id = 2
            </otherwise>
        </choose>
    </where>
</select>

3、trim (where, set)

  • 相当于SQL语句中的修改语句
<update id="updateTrim" parameterType="map">
    update mybatis.blog
    <set>
        title=#{title}
    </set>
    where id=#{id}
</update>

4、foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。

<!-- foreach:   -->
<select id="getBlogmFe" parameterType="map" resultType="blog">
    select * from mybatis.blog where id in

    <foreach collection="list" item="item" index="1" open="(" separator="," close=")">
        #{item}
    </foreach>
</select>

注意

  • collection:指你需要迭代的对象;

  • item:集合项,在下面需要使用;

  • index:索引值;

  • open:迭代值开始的符号;

  • separator:迭代值中间的分隔符;

  • close:迭代值结尾的符号;

5、SQL片段

有的时候,我们可能会将一些功能的部分抽取出来,方便复用!这时候,我们就需要用到SQL片段了。

在代码中使用<sql>标签抽取公共代码,然后使用<include>标签在需要的地方引用公共代码片段。

  • 使用SQL标签抽取公共的部分
<!--  SQL片段:  -->
<sql id="psql">
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>
  • 在需要使用的地方使用Include标签引用即可
<select id="getBlogm" resultType="blog" parameterType="map">
    select * from mybatis.blog
    <where>

        <include refid="psql"></include>

    </where>
</select>

八、简述缓存

一级缓存:存在于每一个测试类中,即一脱离了这个测试类,缓存就会被自动删除。默认开启

二级缓存:存在于每一个对应的Mapper中,即脱离了这个Mapper,缓存就会删除。需要手动开启

其中,开启二级缓存:

1、开启全局缓存

<!--显示的开启全局缓存-->
<setting name="cacheEnabled" value="true"/>

2、在需要使用的二级缓存的Mapper中使用:

<!--在当前Mapper.xml中使用二级缓存-->
<cache/>

也可以自定义缓存参数:

<!--在当前Mapper.xml中使用二级缓存-->
<cache  eviction="FIFO"
       flushInterval="60000"
       size="512"
       readOnly="true"/>

注意:开启二级缓存的时候,我们需要将实体类序列换,不然会出错。

标签:---,name,mapper,log4j,SSM,public,user,Mybatis,id
来源: https://www.cnblogs.com/vxzx/p/15511426.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有