Mybatis操作数据库的两种方式:原生API

 mybatis操作数据的两种方式:原生api和mapper代理对象

1.mybatis的api提供的方法

  •         insert() 增加 delete() 删除  update() 更新
  •         selectOne() 返回一个数据
  •         selectList() 返回多个数据,结果类型为List
  •         selectMap() 返回多个数据,结果类型为Map
  •         select() 返回特殊格式的数据(策略+回调)

原生api总结:

        1.不用写开Connection,给?存值等繁琐的jdbc代码

        2.总清单文件只写一次,子清单文件可以写多个,都放的sql语句

        3.调用原生api,指定好sql语句的id,参数类型和结果类型即可

        4.修改sql语句只需要修改子清单文件,不用修改源代码

        5.针对查询而言,返回的数据结构(集合)丰富,不用程序员把ResultSet中的数据转换为集合对象。

mapper代理对象模式:底层用法还是原生api

2.连接数据库操作流程

(1)连接池池数据源关闭所有连接(关掉老连接)

(2)开启 jdbc

(3)创建连接connection,即mysql的连接对象

(4)seting autocommit to false开链接 ,开启事务

(5)根据方法ID在user.xml的找到对应id 的sql语句   

  • preparing预编译,(statement每个造执行计划,非常耗费时间)
  •         参数、返回值

(6)事务关闭

(7)关闭jdbc

(8)将连接还到连接池内

补充说明:

1.只要异常中的sqlSession为null,就一定是清单文件中有错误

2.给mybatis项目添加日志输出

        a.导入log4j.jar

        b.在项目的类路径下添加一个log4j.properties,logging初始化, ibatis日志管理实现适配器

连接数据库的时候可能存在的编码问题:

java.sql.SQLException: Unknown initial character set index ‘255‘ received from server.-CSDN博客

3.数据库操作

select语句提供了很丰富的结果数据结构

3.1 增删改查

 rowAffect=sqlSession.insert("insertUser",user);

 rowAffect=sqlSession.delete("deleteUserById",id);

 rowAffect=sqlSession.insert("insertUser",user);

红色标注部分为id, 根据对应Id在子清单文件中找到sql语句,并执行

xxDao.java

    public int addUser(User user);
    public int deleteUser(Integer id);
    public int updateUser(User user);

xxDaoImpl.java

public int addUser(User user) {
        int rowAffect=0;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            rowAffect=sqlSession.insert("insertUser",user);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return rowAffect;
    }

    @Override
    public int deleteUser(Integer id) {
        int rowAffect=0;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            rowAffect=sqlSession.delete("deleteUserById",id);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return rowAffect;
    }

    @Override
    public int updateUser(User user) {
        int rowAffect=0;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            rowAffect=sqlSession.update("updateUser",user);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return rowAffect;
    }

user.xml子清单文件

    <!--插入用户-->
    <insert id="insertUser"
            parameterType="org.example.entity.User">
        insert into t_user(
            user_name,
            user_password,
            address)
        values(
            #{name},
            #{password},
            #{address}
        );
    </insert>
    <!--删除用户-->
    <delete id="deleteUserById"
            parameterType="java.lang.Integer">
        delete from t_user
        where id=#{id};
    </delete>
    <!--根据id更新用户-->
    <update id="updateUser"
            parameterType="org.example.entity.User">
        update t_user set
            user_name=#{name},
            user_password=#{password},
            address=#{address}
        where
            id=#{id}
    </update>

单元测试:

    @Test
    public void addUser() {
        UserDao userDao=new UserDaoImpl();
        //假数据
        User user=new User();
        user.setName("add");
        user.setPassword("654321");
        user.setAddress("测试用例");
        Integer rowAffect=userDao.addUser(user);
        System.out.println(rowAffect);
    }

    @Test
    public void deleteUser() {
        UserDao userDao=new UserDaoImpl();
        Integer rowAffect=userDao.deleteUser(3);
        System.out.println(rowAffect);
    }

    @Test
    public void updateUser() {
        UserDao userDao=new UserDaoImpl();
        //假数据
        User user=new User();
        user.setId(3);
        user.setName("addUser");
        user.setPassword("654321");
        user.setAddress("单元测试");
        Integer rowAffect=userDao.updateUser(user);
        System.out.println(rowAffect);
    }

结果展示:

增加一个数据User

​更新id=3的数据

删除id=3的数据

特别的:子清单文件中<insert>、<select>等标签并没有进行判断,Mybatis仅对语句进行判断然后执行。从底层调用来说update\insert调用的是同一个底层方法

3.2 selectOne

查询并返回一个结果

xxDao.java

   public User findUserById(Integer id);

xxDaoImpl.java

    @Override
    public User findUserById(Integer id) {
        User user=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            user=sqlSession.selectOne("findUserById",1);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return user;
    }

user.xml

   <!--根据id获得用户信息-->
    <select id="findUserById"
            resultType="org.example.entity.User"
            parameterType="java.lang.Integer">
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
        where id = #{id}
    </select>

单元测试:

    @Test
    public void findUserById() {
        UserDao userDao=new UserDaoImpl();
        User user=userDao.findUserById(1);
        System.out.println(user);
    }

结果展示:

3.3selectList

查询并返回一个List类型的结果,List里的数据类型可以是业务对象类型,如User; 也可以以Map<Integer,Object> 形式返回对象信息,map中的key是属性名,值是属性值。

xxDao.java

    //返回list结构
    public List<User> findAllUser1();
    public List<Map<String,Object>> findAllUser2();

xxDaoImpl.java

 @Override
    public List<User> findAllUser1() {
        List<User> userList=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            userList=sqlSession.selectList("findAllUser1SqlId");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userList;
    }

    @Override
    public List<Map<String, Object>> findAllUser2() {
        List<Map<String, Object>> userList=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            userList=sqlSession.selectList("findAllUser2SqlId","id");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userList;
    }

user.xml

    <!--查所有返回list<User>-->
    <select id="findAllUser1SqlId"
            resultType="org.example.entity.User"
            >
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
    </select>

    <!--查所有返回list<Map>-->
    <select id="findAllUser2SqlId"
            resultType="java.util.Map"
    >
        select
            id,
            user_name,
            user_password,
            address
        from t_user
    </select>

单元测试:

    @Test
    public void findAllUser1() {
        UserDao userDao=new UserDaoImpl();
        List<User> userList=userDao.findAllUser1();
        for(User user:userList){
            System.out.println(user);
        }

    }

    @Test
    public void findAllUser2() {
        UserDao userDao=new UserDaoImpl();
        List<Map<String, Object>> userList=userDao.findAllUser2();
        for(Map<String, Object> user:userList){
            System.out.println(user.toString());
        }
    }

结果展示:

返回List<User>

返回List<Map<String,Object>>

3.4selectMap

查询并返回一个Map类型的结果,key是指定的属性,Map里的key值数据类型可以是业务对象类型,如User; 也可以以Map<Integer,Object> 形式返回对象信息,map中的key是属性名,值是属性值。

userMap=sqlSession.selectMap("findAllUser3SqlId","id");

userMap=sqlSession.selectMap("findAllUser3SqlId","id");

红色表示将id指定为最外层Map的key值, 也可将其他属性设置为key值。

xxDao.java

    //返回map结构
    public Map<Integer,User> findAllUser3();
    public Map<Integer,Map<String,Object>> findAllUser4();

xxDaoImpl.java

  @Override
    public Map<Integer, User> findAllUser3() {
        Map<Integer, User> userMap=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            //这里是将id作为key了
            userMap=sqlSession.selectMap("findAllUser3SqlId","id");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userMap;
    }

    @Override
    public Map<Integer, Map<String, Object>> findAllUser4() {
        Map<Integer, Map<String, Object>> userMap=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            //这里是将id作为key了
            userMap=sqlSession.selectMap("findAllUser4SqlId","id");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userMap;
    }

user.xml

   <!--查所有返回Map<User>-->
    <select id="findAllUser3SqlId"
            resultType="org.example.entity.User"
    >
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
    </select>

    <!--查所有返回Map<Map>-->
    <select id="findAllUser4SqlId"
            resultType="java.util.Map"
    >
        select
            id,
            user_name,
            user_password,
            address
        from t_user
    </select>

单元测试:

    @Test
    public void findAllUser3() {
        UserDao userDao=new UserDaoImpl();
        Map<Integer,User> userMap=userDao.findAllUser3();
        for(Integer key:userMap.keySet()){
            System.out.println(key+"——>"+userMap.get(key).toString());
        }
    }

    @Test
    public void findAllUser4() {
        UserDao userDao=new UserDaoImpl();
        Map<Integer,Map<String,Object>> userMap=userDao.findAllUser4();
        for(Integer key:userMap.keySet()){
            System.out.println(key+"——>"+userMap.get(key).toString());
        }
    }

结果展示:

Map<String,Object>

Map<String,Map<String,Object>>

3.5select返回自定义数据结构

select()是mybatis留给程序员的自定义接口,其可以返回程序员自定义的数据结构,可以回一个map,也可以是实体对象

这里以JsonString 为指定数据结果为例进行实现

select()可以处理自定义的特殊结构,

ResultHandler<> 是带泛型的接口,我们自定义的resultHandler,如JsonResultHandler 均实现ResultHandler<>接口

其中:

@Override

public void handleResult(ResultContext<? extends User> resultContext) {}

handleResult没有返回值,通过额外的方法将结果进行返回,如 public String getJson(){}

resultHandler处理数据结构的过程:

        resultHandler中handleResult每调用一次,处理一个对象

        返回一个数据,将数据处理为指定类型

        循环调用处理结果集中的所有对象

xxDao.java

    //自定义结构返回
    public String findAllUser5();

xxDaoImpl.java

为了返回指定的数据结构,我们在resultHandler里设定返回格式。

    @Override
    public String findAllUser5() {
        String users=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            //循环多次
            JsonResultHandler resultHandler=new JsonResultHandler();
            sqlSession.select("findAllUser5SqlId",resultHandler);
            users=resultHandler.getJson();
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return users;
    }
    //内部类
    class JsonResultHandler implements ResultHandler<User>{
        //用于追加内容
        StringBuilder sb=new StringBuilder("[");

        //回调一次,返回一个对象
        //结构:  ["1":{1:2,2:3},"2":{1:2,2:3}]
        @Override
        public void handleResult(ResultContext<? extends User> resultContext) {
            //获取用户数据
            User user=resultContext.getResultObject();
            //封装成json串
            sb.append("{");
            sb.append("\"id\":");
            sb.append(user.getId()+",");
            sb.append("\"name\":");
            sb.append("\""+user.getName()+"\",");
            sb.append("\"password\":");
            sb.append("\""+user.getPassword()+"\",");
            sb.append("\"address\":");
            sb.append("\""+user.getAddress()+"\"");
            sb.append("}");
            sb.append(",");
        }

        public String getJson(){
            String temp=sb.toString();
            //前包后不包
            String temp1= temp.substring(0,temp.length()-1)+"]";
            return temp1;
        }
    }

user.xml

    <!--查所有返回自定义格式-->
    <select id="findAllUser5SqlId"
            resultType="org.example.entity.User"
    >
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
    </select>

单元测试

    @Test
    public void findAllUser5() {
        UserDao userDao=new UserDaoImpl();
        String usersJson=userDao.findAllUser5();
        System.out.println(usersJson.toString());
    }

结果展示

总结:

  • Mybatis 中的 ResultHandler 相当于数据结果集的处理器,它是一个回调函数(Callback),用来处理每一行数据的结果,这个回调函数可以在查询结果处理到一定量时触发,对结果集数据进行定制化处理。
  • ResultHandler 的使用可以大幅提升数据处理的效率,当我们需要处理大量的数据时,一般会使用 ResultHandler 来进行结果的处理,避免一次查询就全部返回结果,浪费内存资源或造成 OOM。

摘自《5.7 mybatis之ResultHandler流式处理数据_resulthandler 修改导出数据-CSDN博客

  • mybatis中的原生 api 方法,select(),实现原理是策略模式 + 方法回调,select可以返回我们自定义的数据格式,例如json

摘自《面向接口编程+策略模式+方法回调一起使用_面向接口编程中接口回调怎么写-CSDN博客

4.设计模式

策略模式: Mybatis的select()方法底层实现是策略模式+回调

策略模式

  • 策略模式(Strategy Pattern)属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
  • 其主要目的是通过定义相似的算法,替换if else 语句写法,并且可以随时相互替换。

摘自《https://www.cnblogs.com/xuwujing/p/9954263.html

5.补充

数据库的游标是什么,有什么用?

1.什么是游标?
        游标Cursor是处理数据的一种方法,用来查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行向前或向后浏览数据的能力;
        游标相当于一个指针,它可以指定结果中的任何位置,允许用户对指定位置的数据进行处理;
        游标可以被看作是一个临时文件,提供了在查询结果集中向前或向后浏览护具、处理结果集中数据的能力。
2.游标的作用是什么?
        游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录进行处理的机制。
        用户可以访问结果集中任意一行数据,在将游标放置到某行之后可以在该行或从该位置的行块上执行操作。
        其实就是用于存放查询出来的多条记录的一个临时变量,我们可以从这个变量中取出我们需要的信息字段。

摘自《https://www.cnblogs.com/wanyuy/p/17098457.html

类的内部类?

内部类可以访问该类定义所在操作域的所有数据,包括私有操作域
内部类可以对该包下的其他类隐藏
内部类可以“破解”java单继承的缺陷

摘自《java----内部类(四种内部类详解)-CSDN博客

为什么说Mybatis是面向接口编程?

面向接口编程:就是为了处理对象之间的协作关系,去实现类之间的通信,模块之间的交互等等而设计出来的编程思想。

MyBatis在采用面向接口编程时,采用实体+接口+映射文件的方式。其中接口是不需要实现类的。

摘自《Mybatis学习笔记5:面向接口编程、注解开发_面向对象编程 mybatis-CSDN博客

摘自《MyBatis学习总结(三)---面向接口编程_mybatis技术-接口编程 实验总结-CSDN博客

注意:

  • sql书写时,列名和属性名对应
  • 同一个命名空间下,id不同相同
  • preparedStatement可以防止sql注入
  • springjdbc同结构——rowMapper
  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis 是一个开源的持久层框架,它可以帮助开发者简化数据库操作。下面是使用 MyBatis 操作数据库的一般步骤: 1. 配置数据库连接:在 MyBatis 的配置文件中,设置数据库连接信息,包括数据库驱动、URL、用户名和密码等。 2. 定义数据模型:创建 Java 类来表示数据库中的表,每个类对应一个表,类的属性对应表的列。 3. 编写 SQL 映射文件:创建一个 XML 文件,定义 SQL 语句和映射关系。在文件中,可以使用 MyBatis 提供的标签来编写 SQL 语句,还可以使用动态 SQL 来实现条件查询等功能。 4. 配置 SQL 映射文件:在 MyBatis 的配置文件中,引入 SQL 映射文件,告诉 MyBatis 哪些 SQL 语句对应哪些方法。 5. 创建 SqlSessionFactory:通过 MyBatis 提供的 SqlSessionFactoryBuilder 类,读取配置文件并创建 SqlSessionFactory 对象。SqlSessionFactory 是一个线程安全的类,用于创建 SqlSession。 6. 创建 SqlSession:通过 SqlSessionFactory 的 openSession 方法创建 SqlSession 对象。SqlSession 是一个用于执行 SQL 语句的接口,它提供了多种方法来操作数据库。 7. 执行 SQL 语句:通过 SqlSession 对象调用相应的方法,执行 SQL 语句。例如,可以使用 selectOne 方法执行查询操作,使用 insert、update 或 delete 方法执行增删改操作。 8. 提交事务和关闭资源:在操作完成后,需要调用 SqlSession 的 commit 方法提交事务,并调用 close 方法关闭资源。 以上是使用 MyBatis 操作数据库的一般步骤,具体的实现方式可以根据项目的需求进行调整和扩展。希望对你有帮助!如果有其他问题,请继续提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值