02_Mybatis

Mybatis

原生jdbc操作数据库分析

package com.test.jdbc;

import com.test.pojo.User;

import java.sql.*;

public class jdbcDemo {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        /**
         *  问题一:,每次链接数据库都需要创建链接,浪费资源
         *  解决: 链接池技术,dbcp,druid,c3p0
         */
        //注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        String url  = "jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8";
        //获取链接
        Connection connection = DriverManager.getConnection(url, "root", "luxingchi");
        /**
         * 问题二:sql语句硬编码
         * 解决:mybatis吧sql语句写在xml文件中
         *
         * 问题三:sql语句传入参数与占位符一一对应,耦合度太高
         * 解决:
         *
         */
        String sql = "select * FROM USER ";
        //创建预编译语句执行平台
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //执行语句
        ResultSet resultSet = preparedStatement.executeQuery();
        /**
         * 问题四:结果集的处理繁琐
         * 希望:查询结果是一条记录则返回一个对象,如果是多个数据则返回一个集合
         */
        //处理结果集
        while (resultSet.next()){
            User user = new User();
            user.setId(resultSet.getInt("id"));
            user.setUsername(resultSet.getString("username"));
            user.setPassword(resultSet.getString("password"));

            System.out.println(user);

        }
        resultSet.clearWarnings();
        preparedStatement.close();
        connection.close();

    }

}

Mybatis快速入门

SqlMapConfig.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>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8" />
                <property name="username" value="root" />
                <property name="password" value="luxingchi" />
            </dataSource>
        </environment>
    </environments>
    <!--关联xml文件-->
    <mappers>
        <mapper resource="UserMapper.xml"></mapper>
    </mappers>

</configuration>
UserMapper.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">
<mapper namespace="test">
    <!--查询所有的用户-->
    <select id="selectUser" resultType="com.test.pojo.User">
        SELECT * FROM USER
    </select>
</mapper>
 /**
     * 测试查询所有的方法
     * @throws IOException
     */
    @Test
    public void testSelectUser() throws IOException {
//      使用构建者模式new一个构建者
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//      使用mybatis提供的Resources.getResourcesAsStream方法读取全局配置文件SqlMapConfig.xml
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
//      使用构建者创建一个工厂
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
//      工厂生产出一个会话
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> users = sqlSession.selectList("test.selectUser");
        for (int i = 0; i < users.size(); i++) {
            User user =  users.get(i);
            System.out.println(user);
        }
        sqlSession.close();
        resourceAsStream.close();
    }
测试结果
User{id=1, username='小林', password='111'}
User{id=2, username='小卢', password='222'}
User{id=3, username='老白', password='333'}
User{id=4, username='小黄', password='444'}

Mybatis的CRUD操作

根据用户id查询用户

UserMapper.xml
 <!--根据id查询用户-->
    <select id="queryById" parameterType="Integer" resultType="com.test.pojo.User">
        SELECT * FROM USER WHERE id = #{id}
    </select>
/**
     * 根据id查询用户名
     */
    @Test
    public void testQueryById () {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = new User();
        User u = sqlSession.selectOne("test.queryById", 1);
        System.out.println(u);
        sqlSession.close();
    }

User{id=1, username='小林', password='111'}

根据用户名模糊查询用户列表

   <!--根据用户名模糊查询用户列表-->
    <select id="queryByUsername" parameterType="String" resultType="com.test.pojo.User">
        SELECT * FROM USER WHERE username LIKE #{username}
    </select>
   /**
     * 根据用户名模糊查询
     */
    @Test
    public void testQueryByUsername() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> list = sqlSession.selectList("test.queryByUsername", "%小%");
        for (int i = 0; i < list.size(); i++) {
            User user =  list.get(i);
            System.out.println(user);
        }
        sqlSession.close();
    }
[DEBUG][2019/06/02 19:30:26497][org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:137)]
Opening JDBC Connection
[DEBUG][2019/06/02 19:30:26682][org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:406)]
Created connection 1320677379.
[DEBUG][2019/06/02 19:30:26683][org.apache.ibatis.transaction.jdbc.JdbcTransaction.setDesiredAutoCommit(JdbcTransaction.java:101)]
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@4eb7f003]
[DEBUG][2019/06/02 19:30:26684][org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)]
==>  Preparing: SELECT * FROM USER WHERE username LIKE ? 
[DEBUG][2019/06/02 19:30:26711][org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)]
==> Parameters: %小%(String)
[DEBUG][2019/06/02 19:30:26730][org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159)]
<==      Total: 3
User{id=1, username='小林', password='111'}
User{id=2, username='小卢', password='222'}
User{id=4, username='小黄', password='444'}

小结

实现添加用户

   <!--添加用户-->
    <insert id="saveUser" parameterType="com.test.pojo.User">
        insert INTO USER(username,password) VALUES (#{username},#{password})
    </insert>
  /**
     * 插入用户
     */
    @Test
    public void testSaveUser() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = new User("卢星驰","123456");
        int i = sqlSession.insert("test.saveUser", user);
        
        System.out.println((i >= 0) ? "成功" : "失败");
    }

成功

添加用户的自增主键返回

  <!--自增主键返回-->
    <insert id="saveUserAndReturn" parameterType="com.test.pojo.User">
        <selectKey order="AFTER" resultType="int" keyProperty="id">
            SELECT last_insert_id()
        </selectKey>
        insert INTO USER (username,password) VALUES (#{username},#{password})
    </insert>
 /**
     * 自增主键返回
     */
    @Test
    public void testSaveUserAndReturn() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = new User();
        user.setUsername("夏琳");
        user.setPassword("123");

        int i = sqlSession.insert("test.saveUserAndReturn", user);
        System.out.println((i >= 0) ? "success" : "feil");
        System.out.println(user);

    }
success
User{id=7, username='夏琳', password='123'}

根据用户id修改用户名

 <!--根据用户名修改id-->
    <update id="upadteById" parameterType="com.test.pojo.User" >
        UPDATE USER SET username=#{username} WHERE id=#{id}
    </update>
  /**
     * 根据更新用户名
     */
    @Test
    public void testUpadteById () {
        SqlSession sqlSession = sqlSessionFactory.openSession();

        sqlSession.update("test.upadteById",new User(1,"更新的名字","1"));
        sqlSession.commit();
        sqlSession.close();
    }

根据用户id删除用户名

<!--根据用户id删除-->
    <delete id="deleteById" parameterType="int">
        DELETE FROM USER WHERE id=#{id}
    </delete>
/**
     * 根据id删除
     */
    @Test
    public void testDeleteById() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        sqlSession.delete("test.deleteById",1);
        sqlSession.commit();
        sqlSession.close();
    }

分析Mybatis解决了原生jdbc的哪些问题

Mybatis开发Dao的两种方式

原生方式

public interface UserMapper {
    //根据id查找
    User queryUserByMapperId (Integer id) throws Exception;
}

public class UserMapperImpl implements UserMapper {

    private SqlSessionFactory sqlSessionFactory;

    /*public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }*/

    public UserMapperImpl(SqlSessionFactory sqlSessionFactory) {
        this.sqlSessionFactory = sqlSessionFactory;
    }

    @Override
    public User queryUserByMapperId(Integer id) throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();
        User user = sqlSession.selectOne("test.queryUserByMapperId", id);

        return user;
    }
}

public class testDao {

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws IOException {
        InputStream stream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        sqlSessionFactory = sqlSessionFactoryBuilder.build(stream);

    }

    @Test
    public void testMapper() throws Exception {
        UserMapper userMapper = new UserMapperImpl(sqlSessionFactory);
//        UserMapper userMapper = new UserMapperImpl();
//        userMapper.
        User user = userMapper.queryUserByMapperId(4);
        System.out.println(user);

    }

Mapper方式

public interface MapperTest {
    //根据id查找
    User queryUserByMapperId (Integer id) throws Exception;
}
<mapper namespace="com.test.mapper.MapperTest">

    <select id="queryUserByMapperId" parameterType="Integer" resultType="user">
        SELECT * from USER WHERE id=#{id}
    </select>
</mapper>
public class testMapper {
    private SqlSessionFactory sqlSessionFactory;

    /**
     * 初始化方法,产生一个SqlSessionFactoryBuilder
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        sqlSessionFactory = sqlSessionFactoryBuilder.build(resourceAsStream);
    }
    /**
     * 动态代理
     */
    @Test
    public void testMapper() throws Exception {

        SqlSession sqlSession = sqlSessionFactory.openSession();
//        获取MapperTest的代理对象
        MapperTest mapper = sqlSession.getMapper(MapperTest.class);
        User user = mapper.queryUserByMapperId(4);
        System.out.println(user);
    }


}

Mybatis全局配置文件的使用

SqlMapConfig.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">

UserMapper.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.dt
        d">

properties文件的引入

properties(属性)

<!--
    properties:引入外部资源文件
    resource:指向classpath下的资源文件路径
    注意事项:优先级问题,外部引入的资源文件的配置项的优先级   高于  子标签property配置信息
-->
<properties resource="db.properties">
    <property name="jdbc.username" value="root1"/>
</properties>

typeAliases别名

mybatis默认支持的别名

别名映射的类型
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
mapMap

自定义别名

<!--
    typeAliases定义别名,主要给pojo定义别名
-->
<typeAliases>
    <!--
        type:给哪个类定义别名
        alias:别名名称
    -->
    <!--<typeAlias type="com.ujiuye.mybatis.pojo.User" alias="user"/>-->

    <!--批量定义别名:package指定要扫描的包路径
        注意:package会扫描包及其子包下的所有类,不要类名相重复的情况,否则异常
    -->
    <package name="com.ujiuye.mybatis.pojo"/>
</typeAliases>


mapper映射器

引入sql语句的xml配置文件,把sql语句加载到内存当中

l 万能型选手,基础crud、原始dao开发、mapper开发都可以使用这种方式

l 针对mapper方式开发dao层,我们进行一个增强(另外两种加载xml的方式)

mapper class属性:执行mapper接口类的全限定类名

​ 前提要求:

​ 1、编译之后 mapper.xml和mapper.class在同一个目录文件夹中

2、两个文件名称相同

<!--
    规范:编译之后,UserMapper接口类的class要和UserMapper.xml在同一个目录中,而且文件名相同
-->
<mapper class="com.ujiuye.mybatis.mapper.UserMapper"/>
<!--批量扫描mapper接口类,其实是扫描到包下面的一个个类,然后再按照<mapper class的形式去加载
    所以,package扫描的要求(规范)和直接使用class属性是一样的
-->
<package name="com.ujiuye.mybatis.mapper"/>


Mybatis的输入类型和输出类型

parameterType

l 传递简单数据类型(String、Int等,八种基本类型及其包装类型就叫做简单数据类型)

参考上面(# 参数名任意, 取 参 参 数 名 固 定 为 v a l u e 字 符 串 取参参数名固定为value字符串 value{value})

l 传递Pojo对象(保存用户,传入pojo对象)

参考上面(不管#还是$取参,参数名为属性名)

l 传递Pojo包装对象

n 需求:使用POJO包装对象,根据用户名模糊查询用户列表

n 什么是Pojo包装对象

//    根据id查找
    User queryUserById(QueryVo queryVo) throws Exception;
  <!--使用复合的方式查询-->
    <select id="queryUserById" parameterType="QueryVo" resultType="user">
        SELECT * from USER WHERE id=#{user.id}
    </select>
/**
     * 通过id查询user表
     */
    @Test
    public void testQueryUserById () throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserDao mapper = sqlSession.getMapper(UserDao.class);
        QueryVo queryVo = new QueryVo();
        User u = new User();
        u.setId(1);
        queryVo.setUser(u);
        User user = mapper.queryUserById(queryVo);
        System.out.println(user);
        sqlSession.close();

    }

resultType

l 输出简单类型

查询user表总记录数

l 输出Pojo对象

参考上面

l 输出Pojo列表

参考上面

resultMap

ResultType:自动映射,要求pojo属性名和查询列名保持一致
	订单表POJO类
package com.ujiuye.mybatis.pojo;

import java.util.Date;

public class Orders {
    // 订单id
    private int id;
    // 用户id
    private Integer userId;
    // 订单号
    private String number;
    // 订单创建时间
    private Date createtime;
    // 备注
    private String note;

    public int getId() {
        return id;
    }

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

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    @Override
    public String toString() {
        return "Orders{" +
                "id=" + id +
                ", userId=" + userId +
                ", number='" + number + '\'' +
                ", createtime=" + createtime +
                ", note='" + note + '\'' +
                '}';
    }
}

<?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">
<mapper namespace="com.ujiuye.mybatis.mapper.OrdersMapper">

    <!--
        resultType:自动映射,要求查询列名和pojo属性名保持一致
            1 最终封装的对象
            2 查询列名和pojo属性名一致
        当不一致的时候,要使用手动映射
        resultMap:配置手动映射
    -->
    <select id="queryOrdersAllList" resultMap="ordersResultMap">
        select * from orders
    </select>


    <resultMap id="ordersResultMap" type="orders">
        <!--手动配置映射关系-->
        <!--
            主键字段不一致的时候使用<id>标签配置
            普通字段不一致的时候使用<result>标签配置
            property严格区分大小写,要和pojo属性名称一致
        -->
        <id column="id" property="id"/>
        <result column="user_id" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/>
    </resultMap>
</mapper>

Mybatis多参数传入

注意:使用Pojo封装多个数据传入Mybatis是一种万能型方式

如果拆分成多个参数传入的话,形如

//    根据用户名和id进行查询
    User queryUserByIdAndUsername(Integer id,String username) throws Exception;

那么在xml中取参的时候,取参参数名为arg0、arg1、arg2…等

arg0 对应第一个参数

arg1 对应第二个参数

arg2 对应第三个参数

arg3 对应第四个参数

……

形如:

<!--使用多参数查询-->
    <select id="queryUserByIdAndUsername" resultType="user">
        SELECT * from USER WHERE id=#{arg0} AND username=#{arg1}
    </select>
org.apache.ibatis.binding.BindingException是MyBatis框架中的一个异常,它表示绑定语句无效或未找到。在你提供的引用中,出现了两个不同的错误信息,分别是com.mybatis.mapper.OrdersMapper.finarray和com.cloud.lowcode.mapper.UserMapper.queryByParam。 这些错误信息表明在MyBatis的映射文件中找不到对应的绑定语句。绑定语句是指在映射文件中定义的SQL语句,用于执行数据库操作。 要解决这个问题,你可以按照以下步骤进行操作: 1. 确保映射文件中存在对应的绑定语句。检查com.project_mybatis02.mapper.Mkk映射文件中是否定义了名为list的绑定语句。 2. 检查绑定语句的命名是否正确。确保绑定语句的名称与映射文件中定义的名称完全一致,包括大小写。 3. 检查映射文件的路径是否正确。确认映射文件的路径与MyBatis配置文件中的路径一致。 4. 检查映射文件是否正确加载。确保映射文件已经正确加载到MyBatis的配置中。 5. 检查映射文件中的命名空间是否正确。确认映射文件中的命名空间与Mapper接口的包路径一致。 6. 检查Mapper接口的方法名是否与绑定语句的id一致。确保Mapper接口中的方法名与映射文件中绑定语句的id一致。 7. 检查Mapper接口的包路径是否正确。确认Mapper接口的包路径与映射文件中的命名空间一致。 8. 检查MyBatis的配置文件是否正确加载了映射文件。确认MyBatis的配置文件中已经正确加载了映射文件。 9. 检查数据库连接是否正常。确保数据库连接配置正确,并且数据库中存在对应的表和字段。 10. 如果以上步骤都没有解决问题,可以尝试重新编译和部署项目,确保所有的文件都已经正确部署。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值