学习MyBatis笔记(一)基础

本文详细介绍了MyBatis的基础使用,包括配置文件、Mapper动态代理方式、优化代码、类型转换器的创建与使用,以及调用存储过程的方法。重点讲解了接口开发与CRUD操作,并给出了易错点提示,例如namespace与接口名的一致性、参数类型的匹配等。此外,还探讨了使用HashMap作为输入参数和处理嵌套查询的情况。
摘要由CSDN通过智能技术生成

介绍:

MyBatis可以简化JDBC操作,实现数据的持久化。
ORM:Object Relational Mapping(概念)
Mybatis是ORM的一个实现
映射:
在这里插入图片描述
orm可以使开发人员像操作对象一样操作数据库表

使用方式一. 基础方式:

1. 官网下包
2. 编写头文件
<?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>
    <environments default="development">
        <!-- default与下方ID一致,可以指定具体哪个配置-->
        <environment id="development">

            <!--事物的提交方式(一般是JDBC)
                JDBC,利用JDBC方式处理方式(commit rollback close)
                MANAGED,将事务交由其他组件托管(spring jobss)默认关闭连接,
                        ↑ 取消关闭:<property name="closeConnection" value="false"/>
            -->
            <!--transactionManager末尾有个结束符号 -->
            <transactionManager type="JDBC"/>
            <!--数据库类型:
                POOLED,传统JDBC(每次访问访问数据库,均要打开关闭数据库,此操作太费性能)
                UNPOOLED,数据库连接池(三方)
                JNDI,从tomcat中获取内置的数据库连接池(数据源)
            -->
            <dataSource type="POOLED">
                <!-- 配置数据库信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!-- 加载映射文件-->
        <mapper resource="personMapper.xml"/>
    </mappers>
</configuration>

 **personMapper.xml**
<?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.xml映射文件的 唯一标识 -->
<mapper namespace="personMapper" >
    <!-- 通过namespace+id定位sql语句 -->
    <!-- parameterType: 输入参数类型
         resultType: 查询返回结果值得类型-->
    <select id="queryPersonById" resultType="edu.mybaits.Person" parameterType="int">
        select * from person where id = #{id}
    </select>
    <!-- 输入、输出参数只能一个,但是可以放集合,实现多输入  -->
    <insert id="addPerson" parameterType="edu.mybaits.Person">
        insert into person(id,name,age) values(#{id},#{name},#{age})
    </insert>
    <update id="updatePerson" parameterType="edu.mybaits.Person">
        update person set name = #{name} , age = #{age} where id = #{id}
    </update>
    <delete id="deletePerson" parameterType="int">
        delete from person where id = #{id}
    </delete>
    <!-- 如果返回值类型如果是个对象无论是单个还是多个,这里都是person不用list -->
    <select id="queryAllPerson" resultType="edu.mybaits.Person">
        select * from person
    </select>
</mapper>

  • 我用的是idea,两个文件都要在pom.xml中声明,否则提示找不到文件
<build>
    <resources>
      <resource>
        <directory>src</directory>
        <includes>
          <include>conf.xml</include>
        </includes>
        <filtering>true</filtering>
      </resource>
      <resource>
      <directory>src</directory>
      <includes>
        <include>personMapper.xml</include>
      </includes>
      <filtering>true</filtering>
      </resource>
    </resources>
    </build>
3. 测试文件
/**
 * @Author: qsX
 * @Time: 2020-09-20 15:25
 * @Description:
 */
public class TestMyBatis {
    public static void main(String[] args) throws IOException {
/*        Person person = queryPersonById(1);
        System.out.println(person);*/
/*        List<Person> list = queryAllPerson();
        System.out.println(list);*/
        Person person = new Person(3,"ww",55);
        int count = updatePerson(person);
        System.out.println(count);

    }
    /**
     * @Description 增加人
     * @Param [person]
     * @Return void
     */
    public static int addPerson (Person person) throws IOException {
        SqlSession session = se();
        String statement = "personMapper." + "addPerson";
        //增加几名学生
        int count = session.insert(statement,person);
        //提交事务
        session.commit();
        session.close();
        return count;
    }
    /**
     * @Description 删除指定学生
     * @Param [id]
     * @Return int
     */
    public static int deletePerson (int id) throws IOException {
        SqlSession session = se();
        String statement = "personMapper." + "deletePerson";
        int count = session.delete(statement,id);
        session.commit();
        session.close();
        return count;
    }
    /**
     * @Description 修改指定学生信息
     * @Param [id]
     * @Return int
     */
    public static int updatePerson (Person person) throws IOException {
        SqlSession session = se();
        String statement = "personMapper." + "updatePerson";
        int count = session.update(statement,person);
        session.commit();
        session.close();
        return count;
    }
    /**
     * @Description 按学号查询人
     * @Param [id]
     * @Return edu.mybaits.Person
     */
    public static Person queryPersonById (int id) throws IOException {
        SqlSession session =se();
        String statement = "personMapper." + "queryPersonById";
        Person person = session.selectOne(statement,id);
        session.close();
        return person;
    }
    /**
     * @Description 查询所有人
     * @Param [id]
     * @Return edu.mybaits.Person
     */
    public static List<Person> queryAllPerson () throws IOException {
        SqlSession session =se();
        String statement = "personMapper." + "queryAllPerson";
        List<Person> list = session.selectList(statement);
        session.close();
        return list;
    }
    /**
     * @Description 生成Sqlsession
     * @Param []
     * @Return org.apache.ibatis.session.SqlSession
     */
    public static SqlSession se () throws IOException {
        //加载MyBabits配置文件(为了访问数据库)
        Reader reader = Resources.getResourceAsReader("conf.xml");
        //sqlSessionFactory  -  connection
        //可以配置build的第二参数指定数据库环境(reader,"xxxxx")
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession session = sessionFactory.openSession();
        return session;
    }
}

使用方式二. mapper的动态代理方式crud、Mybatis接口开发推荐使用):

	约定优于配置
  • 硬编码方式:abc.java -

    Configuration conf = new Configuration();
    conf.setName("myProject");

  • 配置方式:abc.xml -
    <name>myProject</name>

  • 约定:默认值就是myProject

1. 基础环境

mybatis. jar/ojdbc. jar、conf. xml、mapper. xml

2. 不同之处

约定的目标: 省略掉statement,即根据约定直接可以定位出SQL语句

 *      1.        方法名   和mapper.xml文件中的标签ID一致
 *      2.方法中的 输入参数 和mapper.xml中标签的parameterType类型一致
 *      3.方法中的 返回值   和mapper.xml文件中标签的resultType类型一致
 
 *      除了以上约定,要实现接口中的方法 和Mapper. xml中SQL标签一一对应,还需要:
 *      1.namespace的值 就是接口的全类名

接口👇(接口名要和Mapper.xml的namespace一致)

package mybatis;
/**
 * @Author: qsX
 * @Time: 2020-09-23 16:10
 * @Description: 操作Mybatis的接口
 */
public interface personMapper {
    Person queryPersonById(int id);
    void addPerson(Person person);
}
Reader reader = Resources.getResourceAsReader("conf.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession session = sessionFactory.openSession();
        
personMapper personMapper = session.getMapper(mybatis.personMapper.class);
Person person = personMapper.queryPersonById(1);

3. 易错点

  • Mapper.xml时通过接口的全类名找到的, 所以namespace值必须和接口名一致(用 . 连接包名)
    在这里插入图片描述
  • xml文件要放置resources文件中,
  • 还有一个最傻的,记得开服务。。。

三、优化代码

1. 将数据库信息提出来

  • 创建db.properties文件将配置信息写入
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/test
username = root
password = 123456
  • 在conf.xml的<configuration> 中用子标签 <properties resource="db.properties"/>引用调用
  • 优化配置信息,动态引入在这里插入图片描述

2. 全局参数

  • 可以在conf.xml中配置
    在这里插入图片描述

2. 别名(忽略大小写)

  • 可以在conf.xml中配置
    在这里插入图片描述

  • 默认的自带内置常见类别名
    在这里插入图片描述

三、自带处理器(类型转换器)

1. 系统的

在这里插入图片描述

2. 自定义

  • java代码 👉 JDBC类型

      示例:   实体类Student    男:true    女:false      👉      数据库表Student    男:1     女:0
    
a. 创建转换器:需要实现TypeHandler接口
  • 此接口有一个实现类是BaseTypeHandler,因此要实现转换器两种选择(继承实现类,接口都行)
  • set : java 👉 sql , get:sql 👉 java

注意:jdbcType = “INTEGER” (integer需要是大写)

转换器👇

public class BooleanToIntConterver extends BaseTypeHandler<Boolean> {

    /*java(boolean)  →   SQL(number)
    * ps:PreparedStatement对象
    * parameter:java
    * jdbcType:jdbc操作的数据库类型
    * */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Boolean parameter, JdbcType jdbcType) throws SQLException {
        if (parameter) {
            ps.setInt(i,1);
        } else {
            ps.setInt(i,0);
        }
    }
    @Override
    public Boolean getNullableResult(ResultSet rs, String columnName) throws SQLException {
        int sexNum =  rs.getInt(columnName); //rs.getInt(name)
        return sexNum == 1 ? true : false;
    }
    @Override
    public Boolean getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        int sexNum =  rs.getInt(columnIndex);//rs.getInt(1)
        return sexNum == 1 ? true : false;
    }
    @Override
    public Boolean getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        int sexNum =  cs.getInt(columnIndex);
        return sexNum == 1 ? true : false;
    }
}
b. 使用转换器👇
    <!--使用了转换器
        1.如果类中的属性和表中的字段能合理识别,则可以使用resultType,否则(boolean→number)使用resultMap
        2.如果类中的属性和表中的字段能合理识别,则可以使用resultType,否则(id→no)使用resultMap
        -->
    <select id="queryPersonByIdWithConverter" resultType="mybatis.Person" parameterType="int" resultMap="PersonResult">
        select * from person where id = #{id}
    </select>
    <resultMap id="PersonResult" type="mybatis.Person">
    <!--分主键:id,非主键:result-->
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sex" column="sex" javaType="boolean" jdbcType="INTEGER"/>
    </resultMap>

    <!--  使用了转换器 sql语句严格区分大小写#{name}  -->
    <insert id="addPersonWithConverter" parameterType="mybatis.Person">
        insert into person(id,name,sex) values(#{id},#{name},#{sex,javaType=boolean,jdbcType=INTEGER})
    </insert>
c. 新建接口类👇
    Person queryPersonByIdWithConverter(int id);
d. 使用接口类👇
    /**
     * @Description 按学号查询人(有转换器)
     * @Param [id]
     * @Return mybaits.Person
     */
    public static Person queryPersonByIdWithConverter (int id) throws IOException {
        SqlSession session =se();
        personMapper personMapper = session.getMapper(mybatis.personMapper.class);
        Person person = personMapper.queryPersonByIdWithConverter(id);
        session.close();
        return person;
    }
注意:
sql语句严格区分大小写#{name}

四、输入参数:parameterType

1.简单类型:(8个基本类型 + String)

#{}和${}的区别
  1. #{任意值}${value},其中的标识符只能是value
  2. #{}自动给 String类型 加引号 ‘ ’
    ${value}原样输出,不会加单引号(可以手动加'${value}')一般用于动态排序
  3. #{}防止SQL注入 , ${value}不行

2.对象类型:

#{属性名}
${属性名}

3. 嵌套查询:

  • mapper.xml 👇
    <!--  嵌套查询  -->
    <select id="queryPersonByaddress" resultType="mybatis.Person" parameterType="mybatis.Person" >
        select * from person where homeaddress like '%${address.HomeAddress}%' or schooladdress like '%${address.SchoolAddress}%'
    </select>
  • 接口 👇
      List<Person> queryPersonByaddress(Person person);
  • 实现 👇
        Address address = new Address("1","1");
        Person person = new Person();
        person.setAddress(address);
        List<Person> list = queryPersonByaddress(person);
        System.out.println(list);

4. HashMap:

 用MAP中的KEY值匹配占位符#{value},配得上就value替换占位符
  • mapper.xml 👇
    <!--  HashMap条件查询  -->
    <select id="queryPersonBynameOrBySexWithHashMap" resultType="mybatis.Person" parameterType="HashMap" >
        select * from person where name = #{name} or sex = #{sex}
    </select>
  • 接口 👇
    List<Person> queryPersonBynameOrBySexWithHashMap(Map<String,Object> map);
  • 实现 👇
        Map<String,Object> PersonMap = new HashMap<>();
        PersonMap.put("name","zs");
        PersonMap.put("sex",true);
        List<Person> list = queryPersonBynameOrBySexWithHashMap(PersonMap);
        System.out.println(list);

五、Mybatis如何调用存储过程,(示例)

1. 查询某个性别的人总数

  • 在数据库中创建存储过程👇
CREATE PROCEDURE queryCountBySexWithProcedure ( IN q_sex INT, OUT count INT ) BEGIN
	SELECT
		count( 1 ) INTO count 
	FROM
		person 
	WHERE
		sex = q_sex;
END 

SHOW PROCEDURE STATUS; 👉 用于查看数据库中已有的存储过程

  • mapper.xml 👇(数据库语句尽量不要加空格与换行)
    <!--  调用存储过程实现查询  callable  输入参数需要用HashMap -->
    <select id="queryCountBySexWithProcedure" statementType="CALLABLE" parameterType="HashMap">
        {CALL queryCountBySexWithProcedure
        (#{q_sex,jdbcType=INTEGER,mode=IN},#{count,jdbcType=INTEGER,mode=OUT})}
    </select>
  • 接口 👇
    void queryCountBySexWithProcedure(Map<String,Object> map);
  • 实现 👇
		Map<String,Object> Map = new HashMap<>();
        Map.put("q_sex",true);
        queryCountBySexWithProcedure(Map);
        Object count = Map.get("count");
        System.out.println(count);

2. 删除

  • 在数据库中创建存储过程👇
CREATE PROCEDURE delectPersonByIdWithProcedure ( IN id INT ) BEGIN
	DELETE 
	FROM
		person 
	WHERE
	id = id;
END
  • mapper.xml 👇(数据库语句尽量不要加空格与换行)
    <!--  调用存储过程实现删除  callable  -->
    <select id="delectPersonByIdWithProcedure" statementType="CALLABLE" parameterType="HashMap">
        {CALL delectPersonByIdWithProcedure(#{pid,jdbcType=INTEGER,mode=IN})}
    </select>
  • 接口 👇
      void delectPersonByIdWithProcedure(Map<String,Object> map);
  • 实现 👇
        Map<String,Object> Map = new HashMap<>();
        Map.put("pid",4);
        delectPersonByIdWithProcedure(Map);

注意点👇

<transactionManager type="JDBC"/>

当  conf.xml  中的提交方式为手动时(JDBC)需要注意,每次的增删改都需要在最后commit一下!!!

五、resultType输入类型

1. 简单类型

2. 对象类型

当数据库字段与实体类属性名不同,或者类型不同时,用 	resultMap

3. 对象集合类型

虽然输出类型为集合,但是resultType 任然是实体类型,而不是集合类型。 			接口中是集合类型

4. HashMap类型

  • 当返回值为HashMap时,能放多个元素,但只能放单一对象的多个元素
    比如 Student(1,“zs”,23)只能存一个学生的多个元素
    所以如果返回是多个对象,接口中的返回值类型应该写:List<Map<String, Object>>

六、resultMap输入类型

resultMap:实体类的属性数据表的字段: 类型、名字不同时

	注意:当属姓名和字段名不一致时,除了使用resultMap以外,还可以使用resultType+HashMap

1. resultMap

在这里插入图片描述

2. resultType+HashMap

在这里插入图片描述

注意

注意: 开发过程中如果有10个字段,但发现某一个字段结果始终为默认值(0,0.0,null),则可能是表的字段和类属性不匹配
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值