MyBatis的基础定义
MyBatis是一个优秀的持久层框架,它的作用是简化jdbc的复杂操作,让我们更方便的使用数据库
持久层:用于访问数据库(Dao)的一层,都是以**mapper来命名,我的理解是@mapper与IOC中的那个数据层@repority有异曲同工之妙
@Mapper注解:表⽰是MyBatis中的Mapper接⼝程序运⾏时,框架会⾃动⽣成接⼝的实现类对象(代理对象),并给交Spring的IOC容器管理
思维联想:IOC的五大类注解以及@Bean方法注解,和DI中@Autiowed类型注入和@Resource方法名注入的区别。
且MyBatis操作数据库主要有两种方法
1. 注解来操作(简单sql适用) 2. 配置xml文件来操作(复杂sql适用)
MyBatis配置相关文件
1. 配置MyBatis依赖和mysql的驱动 2. 连接数据库,配置yml文件
一、想要配置MyBatis依赖和mysql的驱动,在我们创建项目时引入两个依赖即可,一个是MyBatis Fromwork,一个是Mybatis Driver。
二、连接数据库,配置yml文件,首先把application.perprity(可能拼错了哈)
修改成applicaton.yml文件,然后在里面添加连接数据库的配置(配置代码我放下面了)
spring: datasource: //注意,这里一定要修改成你的数据库的名称代替这里的()即可 url: jdbc:mysql://127.0.0.1:3306/ ()?characterEncoding=utf8&useSSL=false username: //输入你的数据库用户名,一般默认的是root password: //输入你的数据库密码,如果为设置过,系统默认为空,直接写一个空串即可“” driver-class-name: com.mysql.cj.jdbc.Driver
一、注解操作数据库
注解来操作sql数据库的方式就是在mapper的方法上添加相关的注解来调用数据库查询,在返回查询到的数据结果
1.1 @Insert(插入注解)
在方法上添加@Insert注解,代码如下:
@Insert("insert into userinfo (id,username,password,age) values (#{id}," + " #{username},#{password},#{age})") public Integer userinsert1(Integer id,String username,String password,Integer age) ;
大家注意了,这里的#{…}表示的是选中拿去数据值,这里建议和传入的参数名保持一致。
1.2 @Delete(删除注解)
在方法上添加@Delete注解,代码如下:
@Delete("delete from userinfo where id=#{id}") public Integer deleteUser(UserInfo userInfo);
1.3 @Update(修改注解)
在方法上添加@Update注解,代码如下:
@Update("update userinfo set age=#{age} where id=#{id}") public Integer updateUser(UserInfo userInfo);
1.4 @Select(重点:查询注解)
在方法上添加@Select注解,代码如下:
@Select("select * from userinfo where id=#{userid}") public List<UserInfo> getid(Integer userid);
注解解决查询不匹配问题
关于查询不匹配问题:主要是由于数据库字段名与方法映射的名称不同,导致无法赋值而显示为null。
当⾃动映射查询结果时,MyBatis会获取结果中返回的列名并在Java类中查找相同名字的属性(忽略
⼤⼩写)
解决方法:
1. 数据库使用as关键字重命名 2. 使用Results进行字段映射 3. 配置驼峰自动转换(大力推荐,简单省事儿)
一、 关于第一种方法我就不细说了,在查询时给as一下名称,使其能和参数名对应即可
二、 这里主要论述第二、种使用Results的方法,大家注意区分,它与下面使用XML方式的Result很容易混淆。
这里我简单举个栗子,大家把@Results当成中间商就可以,它是在mysql和方法参数中指定他们的映射关系,
请看接下来的代码:
@Results(id="resultMap",value = { @Result(column = "delete_flag",property = "deleteFlag"), @Result(column = "create_time",property = "createTime"), @Result(column = "update_time",property = "updateTime") }) @Select("select * from userinfo") public List<UserInfo> selectUser();
这里可以看出来@Results相当于是一个数组,里面包含了很多个小的元素,其中每个元素通过@Result注解来指定了映射关系,如下图例子中:将delete_flag-映射给了deleteFlag、create_time映射给了createTime、update_time映射给了updateTime,这样就能使传的数据正确接收到了
当然,@Results中的id="resultMap"表示的是将这个方法定义一个名称为resultMap方便在下次使用该相同映射关系时可以直接调用@ResultMap注解添加该名称就可以实现和上面一样的效果。如下面的例子:
@ResultMap(value = "resultMap") @Select("select * from userinfo") public List<UserInfo> selectUser1();
这里小总结一下:
注解中用到了@Results(类似于数组)
@Result(数组中的每个元素,其中每个元素描述了对应的映射关系)
@ResultMap(将前面数组定义好的映射关系直接拿来用)
用到了@Results,@Result ,@ResultMap,注意这里并没有用到@ResultType,这是在xml配置数据库中用到的,一定要捋清他们之间的关系
**三、**配置驼峰自动转换
直接在yml配置文件里添加即可,只要mysql的命名方式和java类型的命名遵循开发者手册中的正确命名方式就能实现自动转换,mysql应该命名为小写加下划线如:user_name,java属性类型命名为userName,在配置下就能生效。
mybatis: configuration: map-underscore-to-camel-case: true #配置驼峰⾃动转换
拓展:@Param(重命名注解)和@OPtions(自增注解)
@Param(重命名注解)
@Parram注解有重命名和绑定参数两种特性,用法也分两种情况
1.如果传入的参数类型不是类属性只是一个变量,使用@Param则只有重命名属性,直接#{命名后的名字即可};
2.如果传入的参数类型为类属性,则不仅有重命名属性还有绑定参数的属性,在#{}时,不仅要使用重命名的名字,还要.出该类中对应的成员名
一、只有变量时
代码如下:
@Insert("insert into userinfo (username) values (#{user})") public Integer userinsert2(@Param("user") String username) ;
二、有类属性时
代码如下:
@Insert("insert into userinfo (id,username,password,age) values (#{userInfo.id}," + " #{userInfo.username},#{userInfo.password},#{userInfo.age})") public Integer userinsert3(@Param("userInfo") UserInfo userInfo) ;
@OPtions(自增注解)
在想要拥有自增属性的方法上添加@Options注解,确定哪一个为自增主键就行了
代码如下:
@Options(useGeneratedKeys = true, keyProperty = "id") @Insert("insert into userinfo (username, age, gender, phone) values (#{userinfo.username},#{userinfo.age},#{userinfo.gender},#{userinfo.phone})") Integer insert(@Param("userinfo") UserInfo userInfo);
- useGeneratedKeys:这会令MyBatis使⽤JDBC的getGeneratedKeys⽅法来取出由数据库内 部⽣成的主键(⽐如:像MySQL和SQL Server这样的关系型数据库管理系统的⾃动递增字 段),默认值:false.
- keyProperty:指定能够唯⼀识别对象的属性,MyBatis会使⽤getGeneratedKeys的返回值或 insert语句的selectKey⼦元素设置它的值,默认值:未设置(unset)
这段代码中的自增主键是id,因此在插入数据时id会自动+1
注意:设置 useGeneratedKeys=true 之后,⽅法返回值依然是受影响的⾏数, ⾃增id 会设置在上述 keyProperty 指定的属性中
二、 XML操作数据库
XML的⽅式需要以下两步:
- 配置数据库连接字符串和MyBatis
- 持久层代码配置
一、配置数据库连接字符串和MyBatis
此步骤需要进⾏两项设置,数据库连接字符串设置和MyBatis的XML⽂件配置
spring: datasource: //注意,这里一定要修改成你的数据库的名称代替这里的()即可 url: jdbc:mysql://127.0.0.1:3306/ ()?characterEncoding=utf8&useSSL=false username: //输入你的数据库用户名,一般默认的是root password: //输入你的数据库密码,如果为设置过,系统默认为空,直接写一个空串即可“” driver-class-name: com.mysql.cj.jdbc.Driver # 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件 mybatis: mapper-locations: classpath:mapper/**Mapper.xml
该配置表示放置xml文件的包名必须是mapper命名,且xml文件的命名必须以…Mapper.xml结尾,如以下图片
二、 持久层配置
数据持久成的实现,MyBatis的固定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="要查询数据的包的全路径限定名"> <select id="queryAllUser" resultType="com.example.demo.model.UserInfo"> select username,`password`, age, gender, phone from userinfo </select> </mapper>
这里的全路径限定名就是java 引入的package的名称+你写的类名
如:路径名"com.example.mybaties_demon.Model"+我的类名"UserInfo"
为"com.example.mybaties_demon.Model.UserInfo"
<mapper> 标签:需要指定 namespace 属性,表⽰命名空间,值为mapper接口的全限定
名,包括全包名.类名
<select> 查询标签:是⽤来执⾏数据库的查询操作的:
◦ id :是和Interface (接⼝)中定义的⽅法名称⼀样的,表⽰对接⼝的具体实现⽅法。
◦ resultType :是返回的数据类型,也就是开头我们定义的实体类.
2.1 xml实现@Insert(插入数据)
Xml代码实现如下:
<insert id="insertUser"> insert into userinfo (username, `password`, age, gender, phone) values (#{userinfo.username},#{userinfo.password},#{userinfo.age},#{userinfo.gender},#{userinfo.phone}) </insert>
其中的id名则是表示修饰的是配置这个类名中的哪一个方法
2.2 xml实现@Delete(删除数据)
Xml代码实现如下:
<delete id="deleteUser"> delete from userinfo where id = #{id} </delete>
其中的id名则是表示修饰的是配置这个类名中的哪一个方法
2.3 xml实现@Update(修改数据)
Xml代码实现如下:
<update id="updateUser"> update userinfo set username=#{username} where id=#{id} </update>
其中的id名则是表示修饰的是配置这个类名中的哪一个方法
2.4 xml实现@Select(重点:查询数据)
Xml代码实现如下:
<select id="queryAllUser" resultType="com.example.demo.model.UserInfo"> select id, username,`password`, age, gender, phone, delete_flag, create_time, update_time from userinfo </select>
其中的id名则是表示修饰的是配置这个类名中的哪一个方法
大家会惊讶的发现,诶,为什么会多出来一个resultType属性呢,这里表示查询结果的类型在哪一个基础包里
,因为UserInfo基本类与我们的mapper数据层路径不一致,这里需要特殊说明一下
属性ResultType主要是告诉我们查询的结果要放在那个类下面,这里就需要提供相应的类的路径了。
XML解决查询不匹配问题
解决办法和注解类似:
- 起别名
- 结果映射
- 开启驼峰命名
其中1,3的解决办法和注解⼀样,不再多说,接下来看下xml如果来写结果映射
<resultMap id="BaseMap" type="com.example.demo.model.UserInfo"> <id column="id" property="id"></id> <result column="delete_flag" property="deleteFlag"></result> <result column="create_time" property="createTime"></result> <result column="update_time" property="updateTime"></result> </resultMap> <select id="queryAllUser" resultMap="BaseMap"> select id, username,`password`, age, gender, phone, delete_flag, create_time, update_time from userinfo </select>
小总结一下:
前面注解中使用@Results、@Result、以及@ResultMap,并没有使用到@ResultType
且注解中的别名是有@Results注解来起别名,而@ResultMap是直接调用就行
XML中使用了@ResultMap、@Result、以及@ResultType,并没有使用到@Results
且XML中的起别名是由@ResultMap来起别名,且有@ResultMap来调用
还请注意区别注解和XML中这两种的区别,极其容易混淆