首页 > 技术文章 > mybatis(上)

qqkkOvO 2020-11-10 16:30 原文

什么是mybatis

  • 持久层框架
  • 支持定制化SQL,存储过程和高级映射
  • 几乎避免了所有的JDBC代码

如何获取mybatis

  • maven仓库
  • Github

持久层

数据持久化

  • 持久化就是将程序的数据从瞬时状态,转化成持久状态
  • 内存数据:断电即失
  • 数据库,io文件持久化

mybatis优点:

  • sql和代码分离,提高了程序的可维护性
  • 提供了映射标签,支持对象与数据库的orm字段关系映射
  • 支持动态sql

编写程序

  1. 导依赖包,mybatis、mysql、junit、注意静态资源到处问题

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.example</groupId>
        <artifactId>MyPractice</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <packaging>jar</packaging>
    
        <!--版本锁定-->
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.7</maven.compiler.source>
            <maven.compiler.target>1.7</maven.compiler.target>
            <spring.version>5.2.2.RELEASE</spring.version>
        </properties>
    
        <dependencies>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.10</version>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.22</version>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.1</version>
            </dependency>
        </dependencies>
        <!--    静态资源导出问题-->
        <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
        </build>
    </project>
    
  2. mybatis配置文件,sqlSesisionConfig.xml

    <?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>
    
        <!-- 配置包的别名,这样我们在mapper中定义时,就不需要使用类的全限定名称,只需要使用类名即可 -->
        <typeAliases>
            <package name="mybatis.pojo"/>
        </typeAliases>
    
        <!-- 数据库配置 -->
        <environments default="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/my?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="666666"/>
                </dataSource>
            </environment>
        </environments>
    
        <!-- mybatis的映射配置文件 -->
        <mappers>
            <mapper resource="mybatis/dao/adminMapper.xml"/>
        </mappers>
    
    </configuration>
    
  3. pojo实体类

    package mybatis.pojo;
    
    /**
     *作者: 柯神_
     *时间: 15:09
     *日期: 2020/11/9
     *User: 蜘蛛啊全是腿儿
    **/
    
    public class Admin {
    
      private long adminId;
      private String adminName;
      private String adminPassword;
    
    
      public long getAdminId() {
        return adminId;
      }
    
      public void setAdminId(long adminId) {
        this.adminId = adminId;
      }
    
    
      public String getAdminName() {
        return adminName;
      }
    
      public void setAdminName(String adminName) {
        this.adminName = adminName;
      }
    
      public String getAdminPassword() {
        return adminPassword;
      }
    
      public void setAdminPassword(String adminPassword) {
        this.adminPassword = adminPassword;
      }
    
      @Override
      public String toString() {
        return "Admin{" +
                "adminId=" + adminId +
                ", adminName='" + adminName + '\'' +
                ", adminPassword='" + adminPassword + '\'' +
                '}';
      }
    }
    
    
  4. dao接口

    public interface AdminDao {
        List<Admin> find();
    }
    
  5. mapper映射文件

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="mybatis.dao.AdminDao">
        <select id="find" resultType="admin" >
            select * from admins
        </select>
    </mapper>
    
  6. 测试

        @Test
        public void mybatis(){
    
            try {
                //通过Resources读取配置文件
                InputStream inputStream = Resources.getResourceAsStream("sqlSessionConfig.xml");
                //通过配置文件去建立一个SqlSessionFactory工厂
                SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
                //SqlSessionFactory工厂生产SqlSession对象
                SqlSession sqlSession = sqlSessionFactory.openSession(true);
                //通过SqlSession对象,拿到动态代理对象
                AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
                List<Admin> admins = adminDao.find();
                System.out.println(admins);
            } catch (IOException e) {
                e.printStackTrace();
            }
    

在编写程序的过程中可能遇到的问题

  • 映射文件没有注册在mybatis的配置文件中

    <!-- mybatis的映射配置文件 -->
        <mappers>
            <mapper resource="mybatis/dao/adminMapper.xml"/>
        </mappers>
    
  • 绑定接口错误

    <mapper namespace="mybatis.dao.AdminDao">
    
  • 方法名不对

    <!--id对应dao接口中的方法名-->
    <select id="find" resultType="admin" >
    
  • maven资源导出问题

        <!--    静态资源导出问题-->
        <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
        </build>
    

万能map

当数据库中的字段过多,应该优先考虑使用Map,key可以不必和类中的属性名一致

	int addByMap(Map<String,Object> map);
    <insert id="addByMap" parameterType="map">
        insert into admins (adminId,adminName,adminPassword) values(#{a},#{b},#{c})
    </insert>
	Map<String,Object> map = new HashMap<>();
            map.put("a","6");
            map.put("b","强强");
            map.put("c","999999");
            int add = adminDao.addByMap(map);
            if (add>0){
                System.out.println(map.get("b") + "插入成功!");
            }		

模糊查询

1.在执行代码的时候传递通配符% %

List<Admins> admins = adminDao.getLike("%神%");
    <select id="getLike" resultType="admins" >
        select * from admins where adminName like #{value}
    </select>

2.在sql拼接中使用通配符

List<Admins> admins = adminDao.getLike("神");
    <select id="getLike" resultType="admins" >
        select * from admins where adminName like "%"#{value}"%"
    </select>

配置文件中

环境配置(environments),可以配置多个环境,但是只能选取一个

    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/my?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="root"/>
                <property name="password" value="666666"/>
            </dataSource>
        </environment>
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/my?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=utf8"/>
                <property name="username" value="admin"/>
                <property name="password" value="99999"/>
            </dataSource>
        </environment>
    </environments>

属性(properties),可以引入外部文件,优先使用外部文件

    <properties resource="db.properties">
        <property name="username" value="root"/>
        <property name="password" value="666666"/>
    </properties>

取别名(typeAliases)

  1. package,为这个包下的所有类取别名,默认当前类名并且首字母变为小写
    <typeAliases>
        <package name="mybatis.pojo"/>
    </typeAliases>
  1. typeAlias, 为当前类取别名
    <typeAliases>
        <typeAlias type="admin" alias="com.my.pojo.Admin"/>
        <typeAlias type="admin2" alias="com.my.pojo.Admin2"/>
    </typeAliases>

3.注解,Alias(" ")标注在类上,为当前类取别名

@Alias("adc")
public class Admin{
    ___________
}

设置(settings)

	<settings>
<!--        缓存是否开启,默认是开启的-->
        <setting name="cacheEnable" value="true"/>
<!--        懒加载,默认为false-->
        <setting name="lazyLoadingEnable" value="false"/>
<!--        开启驼峰命名规则,默认为false-->
        <setting name="mapUnderscoreToCamelCase" value="false"/>
<!--        指定mybatis日志的具体实现-->
        <setting name="logImpl" value="LOG4J"/>
    </settings>

映射器(mappers),用来注册绑定mapper映射文件

  1. 资源路径,resource路径(推荐使用,可以随意用!)

    <mappers>
        <mapper resource="mybatis/dao/adminMapper.xml"/>
        <mapper resource="mybatis/dao/adminMapper1.xml"/>
        <mapper resource="mybatis/dao/adminMapper2.xml"/>
    </mappers>
    
  2. url(可以说已经被淘汰,太繁琐)

    <mappers>
        <mapper url="D:///Users/mybatis/dao/adminMapper.xml"/>
        <mapper url="D:///Users/mybatis/dao/adminMapper1.xml"/>
        <mapper url="D:///Users/mybatis/dao/adminMapper2.xml"/>
    </mappers>
    
  3. class,全限定类名(最好也不要使用,接口名和映射文件必须同名,否则会出现一些问题)

    <mappers>
        <mapper class="mybatis.dao.adminMapper"/>
        <mapper class="mybatis.dao.adminMapper1"/>
        <mapper class="mybatis.dao.adminMapper2"/>
    </mappers>
    
  4. package,将包内的都注册为映射器 (最好也不要使用,接口名和映射文件必须同名,否则会出现一些问题)

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

resultMap,结果集映射

解决实体类的属性名,和数据库中的字段名不一致问题

1.简单结果映射

	<resultMap id="adminMap" type="admins">
        <!--column->数据库字段名,property->实体类的属性名。-->
        <result column="adminId" property="adminId"/>
        <result column="adminName" property="adminName"/>
        <result column="adminPassword" property="password"/>
    </resultMap>

    <select id="getLike" resultMap="adminMap">
        select * from admins where adminName like "%"#{value}"%"
    </select>

2.复杂结果映射

​ 2.1. association,一个复杂类型的关联(一个对象使用这个关联)。适用于一对一和多对一的关系

   <!--按查询嵌套处理   ①查询所有人的信息 ②根据查询出来的外键id,寻找对应的书籍信息
(有点。。。太绕了,莫名其妙的null问题)-->
   <select id="find" resultMap="AB" >
        select * from admins
    </select>
    <resultMap id="AB" type="admins">
        <result column="adminId" property="adminId"/>
        <result column="adminName" property="adminName"/>
        <result column="adminPassword" property="password"/>
        <association property="bookes" column="bookesId"
                     javaType="bookes" select="getB">
        </association>
    </resultMap>

    <select id="getB" resultType="bookes">
        select * from bookes where bookID=#{id}
    </select>
<!--  按结果嵌套处理-->
	 <select id="find" resultMap="AB" >
        select a.adminId,a.adminName,b.bookName,b.detail from admins a,bookes b
        where a.bookesId=b.bookID
    </select>
    <resultMap id="AB" type="admins">
        <result column="adminId" property="adminId"/>
        <result column="adminName" property="adminName"/>
        <result column="adminPassword" property="password"/>
        <association property="bookes" javaType="bookes">
            <result column="bookId" property="bookId"/>
            <result column="bookName" property="bookName"/>
            <result column="bookCounts" property="bookCounts"/>
            <result column="detail" property="detail"/>
        </association>

​ 2.2. collection,一个复杂类型的集合(一个集合使用这个关联),适用于一对多和多对多的关系

<!--  按结果嵌套处理-->
 	<select id="findU" resultMap="BA" >
        select * from admins a,bookes b
        where a.bookesId=b.bookID and b.bookID=#{id}
    </select>
    <resultMap id="BA" type="bookes">
        <result column="bookId" property="bookId"/>
        <result column="bookName" property="bookName"/>
        <result column="bookCounts" property="bookCounts"/>
        <result column="detail" property="detail"/>
        <collection property="admins" ofType="admins">
            <result column="adminId" property="adminId"/>
            <result column="adminName" property="adminName"/>
            <result column="adminPassword" property="password"/>
        </collection>
    </resultMap>
<!--按照查询嵌套处理  (有点。。。太绕了,莫名其妙的null问题)-->
    <select id="findU" resultMap="BA">
        select * from bookes b
        where b.bookID=#{id}
    </select>
    <resultMap id="BA" type="bookes">
        <result column="bookId" property="bookId"/>
        <result column="bookName" property="bookName"/>
        <result column="bookCounts" property="bookCounts"/>
        <result column="detail" property="detail"/>
        <collection property="admins"
                    ofType="admins" select="getAById" column="bookId"/>
    </resultMap>

    <select id="getAById" resultType="admins">
        select * from admins where bookesId=#{bookId}
    </select>

推荐阅读