程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

2023-06(2)

mybatis替换JDBC

发布于2021-11-25 20:46     阅读(809)     评论(0)     点赞(0)     收藏(4)


mybatis替换JDBC

初步替换

准备条件

1.需要一个实体类。

package com.fs.entity;

public class BookType implements Serializable {    
    private Integer bookType_id;    
    private String bookType_name;
    ...//实现无参,有参构造,set/get方法,equals和hashcode方法,toString方法
}

2.需要一个xml文件,用来编写sql语言

<!--文件名 BookTypeMapper.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="abc">    
    <select id="selectById" parameterType="int" resultType="com.fs.entity.BookType">
        SELECT BOOKTYPE_ID,BOOKTYPE_NAME FROM BOOKTYPE WHERE BOOKTYPE_ID=#{id}    
    </select>
</mapper>

3.在mybatis的配置文件添加

<!--
        mapper中的属性
        resource:一般为资源文件。可以不用写java类直接写文件,用命名空间.id的方法调用sql语句

        class:一般为java类,填写类路径
        <mapper class="com.fs.mapper.BookTypeMapper"></mapper>
        并且你对应的xml文件一定要跟类同名,还要在同一个包下,才可以使用class
        除此之外还需要保重xml文件的namespace要与class值相同
    -->
<mappers>    
	<mapper resource="BookTypeMapper.xml"></mapper>
</mappers>

4.需要一个测试类。

@Testpublic void selectAll(){
    //第一步:读取资源文件
	InputStream in = BookTypeMapperTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml"); 
    //第二部:创建SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); 
    //第三步:得到sqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession();    
    //第四步:从命名空间为namespace=abc的xml文件中读取id为selectById的方法并执行
    /**
     * selectOne有两种方法  但都是返回一条sql结果,不可以为多条sql结果
     * selectOne
     * 第一个参数String  是我们的 命名空间.id 的sql语句
     * 第二个参数Object  是我们运行 命名空间.id 时的传入参数
     * selectOne(String)
     * selectOne(String,Object)
     */
    BookType bookType = sqlSession.selectOne("abc.selectById", 1);
    System.out.println(bookType);
    //第五步:关闭得到sqlSession  如果是增删改需要提交 sqlSession.commit();
    sqlSession.close();
}

sqlsession查询语句

SqlSession的查询方法参数意义返回结果
selectOne(String)String表示 命名空间.id 的sql语句1行或没有
selectOne(String,Object)String表示 命名空间.id 的sql语句 Object表示传入参数多行
selectList(String)String表示 命名空间.id 的sql语句返回结果集
selectList(String,Object)String表示 命名空间.id 的sql语句 Object表示传入参数返回结果集

ps:sqlsession查询语句只能传入一个参数,对多参数传入不友好。(后面再解决)

mybatis的Dao层模式

一张表 对应一个实体类, 一个实体类 对应的Dao, 一个Dao 对应一个service

传统模式(一个Dao接口, 一个接口的实现类)Mapper代理模式
缺点实现类的中代码大量相似;statementId 写在代码中,硬编码
优点只需要接口,不需要程序员编写实现类,这个dao接口的实现类由Mybatis动态生成的

代理模式:

​ 1) 静态代理

​ 2) 动态代理模式: 1) JDK: Proxy 2) 第三方框架: cglib

区别之前的传统模式: dao接口称为mapper接口 mybatis推荐的取名

​ 1) 要求的对应的sql映射文件的namespace 写法: 对应Mapper接口的包,类名

​ 2) statement的id 对应的方法的方法名一致

​ 3) sql映射文件名与对应的Mapper接口名一样 UserMapper --> UserMapper.xml

分层的目的屏蔽下一层的技术, 解耦

*Mapper.xml文件中的参数调用

用#{}和${}来表示外面传入的参数

#{} 与${} 区别:

${} 拼接sql sql: select * from tb_user where id = 1 sql注入 慎用

#{} 使用?占位 sql: select * from tb_user where id = ?

如果输入参数是简单数据类型: #{名字随便}

如果mybatis是低版本 比如: 3.3.0 简单数据类型: ${value}

如果是mybatis是高版本, 简单数据类型: ${名字随便取}

如果是类类型: #{},${} 名字都是些属性名

<select id="selectById" parameterType="int" resultType="com.fs.entity.BookType">
        SELECT BOOKTYPE_ID,BOOKTYPE_NAME FROM BOOKTYPE WHERE BOOKTYPE_ID=#{id}    
</select>

上面语句 传入参数parameterType为int 返回结果resultType为java中的某个类(com.fs.entity.BookType)

int为简单数据类型并且版本不低 则可以写#{id},#{iddd},#{idddddd},#{asdfg}等等

也可以写为 i d , {id}, id{iddd}, i d d d d d d , {idddddd}, idddddd{asdfg}等等(该写法不建议,会有sql注入风险)

类中的参数必须与表的字段相同不然在为进行手动映射时会出现映射失败

mybatis: 把表与类进行映射, 字段与属性进行映射: 默认映射规则: 字段名与属性名一致,就能映射成功

如果不一样,映射失败

解决方案:

  1. 写sql语句,给列 取别名(属性名)
 select id userid, username ,password,sex,brithday,address from tb_user  where id = #{value}
  1. 使用来对属性与列进行映射
<resultMap id="userResultMap" type="User">
        <!--id专门为主键列映射
           column: 列名
           property:属性名
        -->
        <id column="id" property="userId"></id>
        <!--非主键列的映射-->
        <result column="username" property="name"></result>
    </resultMap>

 <select id="queryById" parameterType="int"   resultMap="userResultMap">
     

注意: 如果使用resultMap, 一个select的statement不要再使用resultType

resultType与resultMap无法共存的.

关于mapper中的class属性和resource属性

class属性

class:一般为java类,填写类路径
并且你对应的xml文件一定要跟类同名,还要在同一个包下,才可以使用class
除此之外还需要保重xml文件的namespace要与class值相同

在这里插入图片描述

mybatis-config.xml中的配置

在这里插入图片描述

接口方法

在这里插入图片描述

BookTypeMapper.xml

在这里插入图片描述

测试类代码

@Testpublic void selectById(){    
    //第一步:读取资源文件
    InputStream in = BookTypeMapperTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");    
    //第二部:创建SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); 
    //第三步:得到sqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession();    
    //第四步:通过sqlSession得到Mapper类
    BookTypeMapper bookTypeMapper = sqlSession.getMapper(BookTypeMapper.class);  
    //第五步:通过类.方法调用sql语句
    System.out.println(bookTypeMapper.selectById(1));    
    //第六步:关闭得到sqlSession  如果是增删改需要提交 sqlSession.commit();
    sqlSession.close();
}

在这里插入图片描述

resource属性

resource:一般为资源文件。可以不用写java类直接写文件,用命名空间.id的方法调用sql语句

在这里插入图片描述

配置文件

在这里插入图片描述

*mapper.xml的写法

在这里插入图片描述

ps:如果查询所有的信息,在JDBC中返回类型为List 那么在.xml文件中的返回类型是什么

xml中的返回类型依旧是com.fs.entity.BookType类型,因为查到的依旧是书籍类型对象,然后通过selectList添加到List在返回。所以返回类型依旧是对象,而不是集合。

关于多参数传值

  1. 第一种方式:
  public User queryByNameAndPwd(String username,String password);
    <select id="queryByNameAndPwd" resultMap="userResultMap">
        SELECT * FROM  tb_user WHERE username = #{username} AND PASSWORD=#{password}
    </select>

出错:

Caused by: org.apache.ibatis.binding.BindingException: Parameter ‘username’ not found. Available parameters are [0, 1, param1, param2]

解决方案:

 <select id="queryByNameAndPwd" resultMap="userResultMap">
        SELECT * FROM  tb_user WHERE username = #{0} AND PASSWORD=#{1}
    </select>

 <select id="queryByNameAndPwd" resultMap="userResultMap">
        SELECT * FROM  tb_user WHERE username = #{param1} AND PASSWORD=#{param1}
    </select>

解决方案:

可读性高: 可以在Mapper接口的方法参数上添加一个注解@Param

public User queryByNameAndPwd(@Param("username") String username, @Param("password")String password);
   <select id="queryByNameAndPwd" resultMap="userResultMap">
        SELECT * FROM  tb_user WHERE username = #{username} AND PASSWORD=#{password}
    </select>

第二种: 把多个参数封装到一个类中, 体现是面向对象的封装思想

@Data
public class UserCondition {
    private User user;
    //....
    private Date beignDate;
    private Date endDate;

}
Caused by: org.apache.ibatis.binding.BindingException: Parameter 'user' not found. Available parameters are [userCondition, param1]

如果没有在参数添加@Param注解, 获取属性,从参数的属性开始

    public User queryByCondition(UserCondition userCondition);
 <select id="queryByCondition" parameterType="UserCondition" resultMap="userResultMap">
          SELECT * FROM  tb_user   WHERE username = #{user.name} AND PASSWORD=#{user.password}
    </select>

如果参数添加@Param注解,必须从参数开始

 public User queryByCondition(@Param("userCondition")UserCondition userCondition);
 <select id="queryByCondition" parameterType="UserCondition" resultMap="userResultMap">
          SELECT * FROM  tb_user   WHERE username = #{userCondition.user.name} AND PASSWORD=#{userCondition.user.password}
    </select>

关于添加数据后,java类可以得到他的自增长的id

以前通过添加后查询赋值获取到数据库自增生成的id, 需要执行获取生成id的sql语句:

在mapper中可以使用绑定

在数据库中存在一个这样的方法

<!--SELECT LAST_INSERT_ID()  获取最后一次产生的id   必须是在同一次会话-->

<insert id="addUser" parameterType="com.fs.entity.User">
    <!--
          resultType: 结果的数据类型
          keyProperty: 把查询的结果赋值那个属性: 属性名
          keyColumn: 把查询的那一列赋值给属性, 如果只有一列,省略
          order:  指定selectKey中的sql语句执行顺序       
					AFTER: 在insertsql之后执行   
					BEFORE  在insertsql之前执行
        -->
    <selectKey resultType="int" keyProperty="id"  order="AFTER">
        SELECT LAST_INSERT_ID()
    </selectKey>
    insert into  tb_user(username,password,sex,brithday,address) values(#{username},#{password},#{sex},#{brithday},#{address})
</insert>

原文链接:https://blog.csdn.net/slow444/article/details/121507706



所属网站分类: 技术文章 > 博客

作者:哦哦好吧

链接:http://www.javaheidong.com/blog/article/331423/6bb5800f4bc987c19816/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

0 0
收藏该文
已收藏

评论内容:(最多支持255个字符)