Mybatis是什么
Mybatis是一个持久层框架。
Mybatis是一个持久层框架,当然作用就是操作数据库的(增删改查).
为什么需要学习Mybatis
Mybatis的理念:让开发者是10%的代码就可以实现数据库的操作。
解决方案: 持久层(DAO)的零实现. 所谓的零实现,就是不用写实现类代码,直接使用接口就可以操作数据库.
Mybatis的定义,提高开发的效率!!!真的写很少代码!!!就可以增删改查。
Mybatis的作用
Mybatis框架能够让我们以最少的代码就可以操作数据库。从而提高开发的效率!!!
--如何将代码减少呢?
持久层的零实现 (不需要写实现类)
可以自动将数据封装到对象里面不需要手工编写映射的关系
Mybatis配置流程图
Resources:资源类,用于读取总配置文件
SqlSessionFactoryBuilder:会话工厂构造类,通过读取的总配置文件构建会话工厂
SqlSessionFactory:会话工厂
SqlSession:会话,就是操作数据库的操作类
入门示例
配置流程说明
1.创建项目,创建lib文件
2.导mybatis包和数据库包进来
3.在src文件创建xml文件配置(
在项目的 src 下面创建 配置文件 mybatis-config.xml
具体配置参考mybatis的官方文档即可
)
<?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"> <!--上面是约束,必须的不变的--> <!-- mybatis 配置标签,内部就是mybatis的具体配置 --> <configuration> <!-- mybatis的环境配置 default :默认使用环境,值就是下面环境的id --> <environments default="mysql"> <!-- mybatis的具体某一个环境 --> <environment id="mysql"> <!-- MyBatis操作需要事务管理,默认使用 JDBC JDBC : MyBatis的别名 --> <transactionManager type="JDBC"/> <!-- 配置MyBatis的数据源 (连接池) POOLED(别名) : MyBatis内置的一个连接池 后期和Spring集成使用 ,Druid 阿里巴巴连接池 --> <dataSource type="POOLED"> <!-- 数据库驱动 --> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <!-- url地址 --> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT"/> <!-- 账号 --> <property name="username" value="root"/> <!-- 密码 --> <property name="password" value="gzsxt"/> </dataSource> </environment> </environments> <!-- 配置映射文件 --> <mappers> <mapper resource="cn/zj/mybatis/mapper/UserMapper.xml"/> </mappers> </configuration>
4.编写MyBatisUtil工具类封装公共代码
(
MyBatisUtil工具类的作用主要用于 读取配置文件,创建工厂对象,提供创建SqlSession数据库操作对象的方法
)
package cn.zj.mybatis.util; import java.io.InputStream; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisUtil { private MyBatisUtil() { } //SqlSessionFactory 会话工厂对象 private static SqlSessionFactory factory; //类加载到JVM中就立马执行static代码块,并且只会执行一次 static { //资源文件 String resource = "mybatis-config.xml"; //try(){}catch(Exception e){} try的圆括号内部能够自动释放/关闭资源 try(InputStream inputStream = Resources.getResourceAsStream(resource)) { //创建SqlSessionFactory 对象 factory = new SqlSessionFactoryBuilder().build(inputStream); } catch (Exception e) { e.printStackTrace(); } } /** * 创建SqlSession对象 * @return SqlSession对 */ public static SqlSession openSession() { //创建Session对象 SqlSession session = factory.openSession(); return session; } }
5.创建数据库表对应的实体类
package cn.zj.mybatis.pojo; public class User { private Integer id; private String name; private String password; private Integer age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public User(Integer id, String name, String password, Integer age) { super(); this.id = id; this.name = name; this.password = password; this.age = age; } public User() { super(); } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", password=" + password + ", age=" + age + "]"; } }
6.创建一个操作接口, 创建表对应的映射文件 :UserMapper.xml
package cn.zj.mybatis.mapper; import java.util.List; import cn.zj.mybatis.pojo.User; /* * 使用MyBatis的动态代理开发编写代码遵循四个原则 * 1.映射文件的namespace命名空间的值必须是对应接口的全限定名 2.映射文件的对应功能 id值必须等于映射接口中方法的名称 3.映射文件的参数类型必须和接口中方法的参数类型一致 4.映射文件查询的返回结果类型必须和接口的方法的返回数据类型一致, DML操作返回的受影响的行数,除外 */ public interface UserMapper { /** * 插入用户数据 * @param user 封装有用户信息的User镀锡 * @return 受影响的行数 */ int insertUserInfo(User user); /** * 单行查询 * @param id 主键id * @return 查询结果封装的User对象 */ User selectByPrimaryKey(int id); /** * 多行查询 * @return 结果集封装的对象 */ List<User> selectList(); /** * 删除操作 * @param id 主键id * @return 受影响的行数 */ int deleteByPrimaryKey(int id); /** * 修改操作 * @param user 带有id的user对象 * @return 受影响的行数 */ int updateUserInfo(User user); }
<?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"> <!-- 上面是约束,是不变得 --> <!-- 映射标签,内部就编写具体的映射sql语句 namespace :命名空间,值 必须是 对应接口的全限定名 = 包名 +简单类名 cn.zj.mybatis.mapper.UserMapper --> <mapper namespace="cn.zj.mybatis.mapper.UserMapper"> <!-- <insert id="insertUserInfo" parameterType=""> 插入功能标签 id : 功能唯一标识, 必须接口中对应的方法名一致 parameterType : 参数类型,必须和接口中方法的参数类型一直 keyColumn="" : 结果集对应的主键列 keyProperty="" pojo对象对应结果集主键列的属性 useGeneratedKeys="true" :是否返回自动生成的主键 true 是 --> <insert id="insertUserInfo" parameterType="cn.zj.mybatis.pojo.User" keyColumn="id" keyProperty="id" useGeneratedKeys="true" > <!-- #{对象属性} : OGNL 表达式语言 --> insert into user (username,password,age)values(#{username},#{password},#{age}) </insert> <!-- 单行查询 <select resultType =""> 查询功能的标签 resultType : 返回结果的数据类型,和接口对应方法的返回类型必须一致 --> <select id="selectByPrimaryKey" parameterType="Integer" resultType="cn.zj.mybatis.pojo.User"> select * from user where id= #{id} </select> <!-- 多行查询 无论单行或者多行查询,返回的数据类型都是 对应 pojo 对应的对象类型 --> <select id="selectList" resultType="cn.zj.mybatis.pojo.User"> select * from user </select> <!-- 删除操作 --> <delete id="deleteByPrimaryKey" parameterType="Integer"> delete from user where id= #{id} </delete> <update id="updateUserInfo" parameterType="cn.zj.mybatis.pojo.User"> update user set username = #{username},password = #{password},age = #{age} where id = #{id} </update> </mapper>
7.测试类
package cn.zj.mybatis.test; import static org.junit.Assert.*; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import cn.zj.mybatis.mapper.UserMapper; import cn.zj.mybatis.pojo.User; import cn.zj.mybatis.util.MyBatisUtil; public class UserMapperTest { @Test public void testInsertUserInfo(){ //1.创建SqlSession会话对象 SqlSession session = MyBatisUtil.openSession(); //2.创建UserMapper接口的代理对象(Java的动态代理) UserMapper mapper = session.getMapper(UserMapper.class); User user=new User(null,"xijhef","wffew",10); //3.执行插入方法 int row = mapper.insertUserInfo(user); //4.提交事务(Mybatis默认DML操作需要手动提交事务) System.out.println(row); session.commit(); //5.关闭session session.close(); } @Test public void testDelet(){ SqlSession openSession = MyBatisUtil.openSession(); UserMapper userMapper = openSession.getMapper(UserMapper.class); User user = userMapper.selectByPrimaryKey(1); System.out.println(user); openSession.close(); } @Test public void testUpdata() throws Exception { SqlSession openSession = MyBatisUtil.openSession(); UserMapper mapper = openSession.getMapper(UserMapper.class); User user = new User(1,"ewf","efwef",20); int updateUserInfo = mapper.updateUserInfo(user); openSession.commit(); openSession.close(); } @Test public void testByPrimaryKey() throws Exception { SqlSession openSession = MyBatisUtil.openSession(); UserMapper mapper = openSession.getMapper(UserMapper.class); User users = mapper.selectByPrimaryKey(1); openSession.close(); } @Test public void testSelectList() throws Exception { SqlSession openSession = MyBatisUtil.openSession(); UserMapper mapper = openSession.getMapper(UserMapper.class); List<User> selectList = mapper.selectList(); for(User user : selectList) { System.out.println(user); } openSession.close(); } }
ResultMap 手动映射
MyBatis的查询结果集都是自动映射封装的,单行查询将数据库一条数据封装成对应的Java对象。多行查询,先将每一行封装成对象,再将每个对象添加到集合中,最后返回一个List集合对象。
但是:必须保证查询结果集和pojo对象的属性名相同,否则无法自动封装
问题: 如何解决查询结果集名称和pojo对象属性不同的映射封装?
解决方案:
- 使用手动映射封装 <ResultMap>标签
- 可以使用mybatis的驼峰命名法
<?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"> <!-- 上面是约束,是不变得 --> <!-- 单行查询 <select resultType =""> 查询功能的标签 resultType : 返回结果的数据类型,和接口对应方法的返回类型必须一致 resultMap : 使用手动映射,值就是 对应手动映射的id值 注意: resultType自动映射和resultMap不能同时使用,一次只能使用一个 --> <select id="selectByPrimaryKey" parameterType="Integer" resultMap="user_map"> <!-- #{对象属性} ,主键理论上任何值都可以 #{abc},#{xxx},可以不用对象属性--> <!-- select * from user where id = #{id} --> select id u_id,username u_username,password u_password,age from user where id = #{id} </select> <!-- 查询结果集手动映射封装标签 <resultMap type="" id=""></resultMap> type :结果集需要封装对象的数据类型 id :唯一标识 --> <resultMap type="cn.zj.mybatis.pojo.User" id="user_map"> <!-- <id column="" property="" javaType="" jdbcType=""/> <id>主键列映射 : column:结果集对应的主键列明 u_id property : pojo 对应主键的属性名称 id javaType :java对应属性类型[可选]- String,Integer jdbcType : java对应数据库类型[可选] - VARCHAR,DATE --> <id column="u_id" property="id" /> <!-- <result column="" property="" javaType="" jdbcType=""/> <result>非主键列映射 : column:结果集对应的主键列明 u_id property : pojo 对应主键的属性名称 id javaType :java对应属性类型[可选]- String,Integer jdbcType : java对应数据库类型[可选] - VARCHAR,DATE --> <result column="u_username" property="username" /> <result column="u_password" property="password" /> <result column="age" property="age" /> </resultMap> <!-- 多行查询 无论单行或者多行查询,返回的数据类型都是 对应 pojo 对应的对象类型 --> <select id="selectList" resultType="cn.zj.mybatis.pojo.User" resultMap="user_map"> select id u_id,username u_username,password u_password,age from user </select> </mapper>
主配置文件说明与细节配置
<environments>:环境集标签,就是用于配置数据库的连接信息的
<environment>:用于配置具体环境参数
<transactionManager>:配置使用的事务类型,JDBC
<dataSource>:配置数据源的参数,POOLED
具体参数参看PooledDataSource的set方法
<property>:配置属性
<mappers>:配置映射文件信息的
<mapper class|resource>:配置具体指定的mapper文件
class:配置使用注解时指定有注解的映射接口
resource:指定映射文件
<properties>:mybatis对propertis文件的支持
<typeAliases>:用于配置别名
<typeHandlers>:用于配置自定义类型处理器.
<settings>:配置Mybatis的默认设置的.
总配置文件的标签顺序
<!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)> |
这句话的意思就是configuration 标签下的标签的顺序以及标签出现的个数的声明
根据这个声明可以看到顺序为:
1.properties
2.settings
3.typeAliases
4.typeHandlers
5.objectFactory
6.objectWrapperFactory
7.reflectorFactory
8.plugins
9.environments
10.databaseIdProvider
11.mappers
DTD规则文件标签的出现的次数说明
如果声明的标签后?:表示出现0-1次
如果声明的标签后*:表示出现0-N次
如果声明的标签后+:表示出现1-N次
如果声明的标签后什么都没有:表示出现1次
别名typeAliases标签
在UserMapper.xml文件中User无论是作为参数还是作为查询返回数据类型,都需要写上全限定名,实际可以写上简单类名即可,但是需要配置别名
MyBatis框架提供了两种别名机制,一种是自定义别名,一种是内置别名
<?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"> <!--上面是约束,必须的不变的--> <!-- mybatis 配置标签,内部就是mybatis的具体配置 --> <configuration> <properties resource="db.properties"/> <!-- 读取 db.properties resource : 资源路径 --> <typeAliases> <!-- .自定义别名:使用包扫描配置别名 <package name="包名">
如果配置成功,在映射文件里面可以直接使用别名
被配置的包下面的所有的类都被取了别名,适用包下面能有大量类 别名就是当前包下面类的简单类名,默认不区分大小 --> <package name="cn.zj.mybatis.pojo"/> <!-- 配置单个类的别名 <typeAlias type="" alias=""/> type:要设置别名的数据类型 alias :别名 --> <!-- <typeAlias type="cn.zj.mybatis.pojo.User" alias="User"/> --> </typeAliases>
<!-- mybatis的环境配置 default :默认使用环境,值就是下面环境的id --> <environments default="mysql"> <!-- mybatis的具体某一个环境 --> <environment id="mysql"> <!-- MyBatis操作需要事务管理,默认使用 JDBC JDBC : MyBatis的别名 --> <transactionManager type="JDBC"/> <!-- 配置MyBatis的数据源 (连接池) POOLED(别名) : MyBatis内置的一个连接池 后期和Spring集成使用 ,Druid 阿里巴巴连接池 --> <dataSource type="POOLED"> <!-- 数据库驱动 --> <!-- 使用类似于 JSP中的EL表达式 ${key}获取 properties配置文件中的值 --> <property name="driver" value="${jdbc.driverClassName}"/> <!-- url地址 --> <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT"/> <!-- 账号 --> <property name="username" value="${jdbc.username}"/> <!-- 密码 --> <property name="password" value="${jdbc.password}"/>
</dataSource> </environment> </environments> <!-- 配置映射文件 --> <mappers> <!-- 读取单个映射文件 --> <mapper resource="cn/zj/mybatis/mapper/UserMapper.xml"/> </mappers> </configuration>
内置别名
所谓的内置别名,就是Mybatis框架自带别名.
Mybatis已经将常用的数据类型的别名内置声明了.所以这些内置的别名不需要配置就可以直接使用.
内置的别名就是,Mybatis框架默认已经设置的别名.
别名 |
映射的类型 |
_byte |
byte |
_long |
long |
_short |
short |
_int |
int |
_integer |
int |
_double |
double |
_float |
float |
_boolean |
boolean |
string |
java.lang.String |
byte |
Byte |
long |
Long |
short |
Short |
int |
Integer |
integer |
Integer |
double |
Double |
float |
Float |
boolean |
Boolean |
date |
java.util.Date |
decimal |
BigDecimal |
bigdecimal |
BigDecimal |
object |
Object |
map |
java.util.Map |
hashmap |
HashMap |
list |
List |
arraylist |
ArrayList |
collection |
Collection |
iterator |
Iterator |
properties 读取配置文件
一般开发会将单独的数据库连接字符串配置到一个独立的 以 .properties 的配置文件中
Mybaits框架中配置文件 的 <properties>标签可以读取配置文件中的内容。并可以使用${}的语法设置给框架的数据库连接操作代码
在classpath下面创建一个db.properties数据库连接配置文件
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8 jdbc.username=root jdbc.password=root |
在mybatis-config.xml主配置文件中配置<properties>标签读取配置文件
<!-- 根标签,在内部配置MyBatis框架信息 --> <configuration>
<!-- 读取classpath下面的 数据库配置文件、 读取以后再下面链接数据库的配置中就可以使用 ${配置文件key} 获取对应的数据库连接相关信息 --> <properties resource="db.properties"/> |
连接数据库的配置修改为 ${key}的方式
--> <environment id="mysql"> <!-- 配置事务管理器 type : 事务管理器的类型,使用的MyBatis框架自定义的一种别名 JDBC :使用原生的JDBC作为事务管理 --> <transactionManager type="JDBC"/> <!-- 配置MyBatis的数据源 type : 配置连接池 POOLED :mybatis内置的一个连接池(默认) 后期都交给spring管理了,配置 dbcp连接池,阿里巴巴的 druid连接池 --> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> |