Mybatis之基本操作

本文详细介绍了Mybatis中增删改操作的实现,包括单个insert、delete、批量select和单个update。同时涵盖了数据输入的多种类型,如简单类型、实体类、Map参数等,以及数据输出的各种形式,如简单类型、实体对象、Map和List。此外,还讨论了resultMap、自增主键处理和防止SQL注入的方法。
摘要由CSDN通过智能技术生成

一、Mybatis中的增删改操作

1、单个insert

mapper接口中

/**
 * 增加一本书
 */
int addBook(BookEntity bookEntity);

①使用xml写sql

<!--    因为配置了别名,所以parameterType不需要写全类名-->
    <insert id="addBook" parameterType="BookEntity">

-- 参数与BookEntity中的属性对应,因为mybatis会调用get方法获取BookEntity中的属性

        insert into books values (#{id},#{name},#{price})
    </insert>

②使用注解

@Insert("insert into books values (#{id},#{name},#{price})")
int addBook(BookEntity bookEntity);

测试:

    @Test
    public void test(){
        BookEntity bookEntity=new BookEntity();
        bookEntity.setId(3);
        bookEntity.setName("Mybatis从入门到精通");
        bookEntity.setPrice(88);
        int i = bookMapper.addBook(bookEntity);
        if (i==1){
            System.out.println("添加成功");
        }else {
            System.out.println("添加失败");
        }
    }

2、单个delete

/**
 * 根据id删除图书
 */
int deleteBookById(Integer id);

①使用xml写sql

<delete id="deleteBookById" parameterType="java.lang.Integer">
    delete from books where id=#{id}
</delete>

②使用注解

@Delete("delete from books where id=#{id}")
int deleteBookById(Integer id);

测试

@Test
public void test(){
    int i = bookMapper.deleteBookById(3);
    if (i>0){
        System.out.println("删除成功");
    }
    else {
        System.out.println("删除失败");
    }
}

3、批量select

/**
 * 查询全部
 */
List<BookEntity> selectList();

①使用xml写sql

<!--    查List的时候resultType是List里面的类型-->
    <select id="selectList" resultType="BookEntity">
        select * from books
    </select>

②使用注解

@Select("select * from books")
List<BookEntity> selectList();

测试

@Test
public void test(){
    List<BookEntity> bookEntities = bookMapper.selectList();
    bookEntities.forEach(System.out::println);
}

4、单个update

/**
 * 修改图书
 */
int updateById(BookEntity bookEntity);

①使用xml写sql

<update id="updateById" parameterType="BookEntity">
    update books set name=#{name},price=#{price} where id=#{id}
</update>

②使用注解

@Update(" update books set name=#{name},price=#{price} where id=#{id}")
int updateById(BookEntity bookEntity);

测试:

@Test
public void test(){
    BookEntity bookEntity=new BookEntity();
    bookEntity.setId(1);
    bookEntity.setName("Mybatis从入门到入土");
    bookEntity.setPrice(1999);
    int i = bookMapper.updateById(bookEntity);
    if (i==1){
        System.out.println("修改成功");
    }
    else {
        System.out.println("修改失败");
    }
}

二、数据输入

1、单个简单的类型

mapper接口:

@Select("select * from books where id=#{id}")
BookEntity selectById(Integer id);

单个简单的参数,可以使用任意名称

eg:

@Select("select * from books where id=#{value}")
BookEntity selectById(Integer id);

2、实体类类型参数

Mybatis会根据#{}中传入的数据,加工成getXxx()方法,通过反射在实体类对象中调用这个方法,从而获取到对应的数据。填充到#{}这个位置。所以要保证#{}中的名称与实体类中的名称一致

mapper接口:

@Update(" update books set price=#{price} where name=#{name} ")
  int updateByName(BookEntity bookEntity);

3、零散的简单类型数据

待解决问题:当出现多个简单类型参数,mybatis通过反射找不到对应的参数

问题解决:使用 @Param注解指定参数名称

mapper接口:

@Select("select * from books where id=#{id} and  name=#{name} and price=#{price}")
List<BookEntity> selectAll(@Param("id") Integer id, @Param("name") String name, @Param("price") Integer price);

4、Map参数的数据类型

①使用场景

有很多零散的参数需要传递,但是没有对应的实体类类型可以使用。使用@Param注解一个一个传入又太麻烦了。所以都封装到Map中

②对应关系

#{}中写Map中的key,会将key对应的将map中 的value封装进去

mapper接口:

这里采用注解,xml配置文件一样

@Select("select * from books where name=#{name} and description=#{description} ")
List<BookEntity> selectByMap(Map<String,String> map);

测试类:

@Test
public void test(){
    Map<String,String> map=new HashMap<>();
    map.put("name","Mybatis");
    map.put("description","是一本好书");
    List<BookEntity> bookEntities = bookMapper.selectByMap(map);
    bookEntities.forEach(System.out::println);


}

三、数据输出

1、返回单个简单类型数据

设置resultType为int(别名),也可以使用全类名

<select id="selectEmpCount" resultType="int">
    select count(*) from t_emp
</select>

2、返回实体类对象

<!-- resultType属性:指定封装查询结果的Java实体类的全类名,如果设置了别名,也可以直接使用别名 -->
<select id="selectEmployee" resultType="com.atguigu.mybatis.entity.Employee">
    <!-- Mybatis负责把SQL语句中的#{}部分替换成“?”占位符 -->
    <!-- 给每一个字段设置一个别名,让别名和Java实体类中属性名一致 -->
    select username , pwd from user where user_id=#{id}
</select>

如果数据库中的表名与实体类的名称不一致?

1、在查询过程中起别名

<select id="selectEmployee" resultType="com.atguigu.mybatis.entity.Employee">
    <!-- Mybatis负责把SQL语句中的#{}部分替换成“?”占位符 -->
    <!-- 给每一个字段设置一个别名,让别名和Java实体类中属性名一致 -->
    select username, pwd as password from user where user_id=#{id}
</select>

2、使用 resulteMap(文章 下面会提到)

3、返回Map类型

适用于SQL查询返回的各个字段综合起来并不和任何一个现有的实体类对应,没法封装到实体类对象中。能够封装成实体类类型的,就不使用Map类型。

eg:查询图书的总数量和平均价格

mapper接口:

Map<String,Object> selectNumAndAvg();

xml配置文件:

<select id="selectNumAndAvg" resultType="java.util.Map" >
    select count(*) ,avg(price) from books
</select>

测试类:

@Test
public void test01(){
    Map<String, Object> stringObjectMap = bookMapper.selectNumAndAvg();
    //遍历map
    for (Map.Entry<String, Object> stringObjectEntry : stringObjectMap.entrySet()) {
        System.out.println(stringObjectEntry.getKey());
        System.out.println(stringObjectEntry.getValue());
    }
}

运行结果:

avg(price)
50.5000
count(*)
2

查询的时候起别名

<select id="selectNumAndAvg" resultType="java.util.Map" >
    select count(*) as allNum ,avg(price) as avgPrice from books
</select>

返回的map中的key就变为起的别名

avgPrice
50.5000
allNum
2

4、返回List类型

查询结果返回多个实体类对象,希望把多个实体类对象放在List集合中返回。此时不需要任何特殊处理,在resultType属性中还是设置实体类类型即可

mapper接口:

/**
 * 查询全部
 */
List<BookEntity> selectList();

xml配置文件:

<!--    查List的时候resultType是List里面的类型-->
    <select id="selectList" resultType="BookEntity">
        select * from books
    </select>

5、返回自增主键

mapper接口:

/**
 * 增加一本书
 */
int addBook(BookEntity bookEntity);

xml配置文件:

<!--    因为配置了别名,所以parameterType不需要写全类名-->
    <!-- useGeneratedKeys属性字面意思就是“使用生成的主键” -->
    <!-- keyProperty属性可以指定主键在实体类对象中对应的属性名,Mybatis会将拿到的主键值存入这个属性 -->

    <insert id="addBook" parameterType="BookEntity" useGeneratedKeys="true" keyProperty="id">
        insert into books (name,price,description) values (#{name},#{price},#{description})
    </insert>

测试类:

@Test
public  void test02(){
    BookEntity bookEntity=new BookEntity();
    bookEntity.setName("Mybatis从入门到精通");
    bookEntity.setPrice(88);
    bookEntity.setDescription("非常好");
    bookMapper.addBook(bookEntity);
    System.out.println(bookEntity);
}

返回结果:

BookEntity(id=4, name=Mybatis从入门到精通, price=88, description=非常好)

注意:

Mybatis是将自增主键的值设置到实体类对象中,而不是以Mapper接口方法返回值的形式返回。

不支持自增主键的数据库

而对于不支持自增型主键的数据库(例如 Oracle),则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用

<insert id="insertEmployee" 
		parameterType="com.atguigu.mybatis.beans.Employee"  
			databaseId="oracle">
		<selectKey order="BEFORE" keyProperty="id" 
                                       resultType="integer">
			select employee_seq.nextval from dual 
		</selectKey>	
		insert into orcl_employee(id,last_name,email,gender) values(#{id},#{lastName},#{email},#{gender})
</insert>

或者是

<insert id="insertEmployee" 
		parameterType="com.atguigu.mybatis.beans.Employee"  
			databaseId="oracle">
		<selectKey order="AFTER" keyProperty="id" 
                                         resultType="integer">
			select employee_seq.currval from dual 
		</selectKey>	
	insert into orcl_employee(id,last_name,email,gender) values(employee_seq.nextval,#{lastName},#{email},#{gender})
</insert>

resultMap元素

待解决问题: 结果集(表)中的列名和对象中的字段名称不匹配

如果是UserName与username不匹配,可以配置驼峰映射

mybatis:
#开启驼峰映射
configuration:
  map-underscore-to-camel-case: true

那如果是两个完全无关的属性名呢?

解决方案: 使用resultMap元素
eg:

   <resultMap id="UserMapper" type="UserEntity">
        <result column="u_id" property="id" />
        <result column="u_name" property="name" />
        <result column="u_pwd" property="pwd" />
    </resultMap>
<!-- 此处就使用 结果集对象映射, UserMapper -->
<select id="queryUserList" resultMap="UserMapper">
    select u_id, u_name, u_pwd from user1;
</select

{}和${}的区别

#{}方式

Mybatis会在运行过程中,把配置文件中的SQL语句里面的#{}转换为“?”占位符,发送给数据库执行。

配置文件中的SQL:

<delete id="deleteEmployeeById">
    delete from t_emp where emp_id=#{empId}
</delete>

实际执行的SQL:

delete from t_emp where emp_id=?

${}方式

将来会根据${}拼字符串

①SQL语句

<select id="selectEmployeeByName" resultType="com.atguigu.mybatis.entity.Employee">
    select id ,ame ,salary  from t_emp where name = '${empName}'
</select>

注意加上’'(单引号),否则sql将变成

eg:

  select id ,ame ,salary  from t_emp where name = 张三

传入的参数就不会加’',而是直接被拼接上去

应用场景举例

在SQL语句中,数据库表的表名不确定,需要外部动态传入,此时不能使用#{},因为数据库不允许表名位置使用问号占位符,此时只能使用${}

eg:

@Select("select * from ${tableName}")
List<BookEntity> selectListByTableName(String tableName);

如果使用#{},sql就会变成select * from ‘tableName’

其他情况,只要能用#{}肯定不用${},避免SQL注入。

演示sql注入:

eg:将name为Mybatis从入门到入土的图书价格修改为1元

<update id="updateByName" parameterType="BookEntity">
    update books set price=#{price} where name=${name}
</update>
@Test
public void test(){
    BookEntity bookEntity=new BookEntity();
    bookEntity.setId(1);
    bookEntity.setName("'Mybatis从入门到入土' or 1=1 ");
    bookEntity.setPrice(1);
    int i = bookMapper.updateByName(bookEntity);
    System.out.println("共修改"+i+"条数据");
}

结果将数据库中所有的book的价格全部修改为1元

提取sql片段

    <sql id="Base_Column_List">
        id,name,description,
        price
    </sql>
    <select id="selectByBookId" resultType="com.iflytek.pojo.BookEntity">
        select <include refid="Base_Column_List"></include>
            from books where id=#{id}
    </select>

使用include引入

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值