1.什么是Mybatis?
Mybatis是一个优秀持久层框架,提供了对数据库的一系列操作(增删改查)。Mybatis可以避免重复的写JDBC代码,让我们以较少的代码实现对数据库的操作,从而提高开发效率。Mybatis的特点是持久层(Dao)零实现,即只需要写接口,不需要写实现类。
2.Mybatis的配置
2.1 配置流程图
Resources:资源类,用于读取总配置文件
SqlSessionFactoryBuilder:会话工厂构造类,通过读取的总配置文件构建会话工厂
SqlSessionFactory:会话工厂
SqlSession:会话,就是操作数据库的操作类
2.2 配置流程说明
--获得数据库连接
第一步:导入jar包
第二步:创建主配置文件(文件名推荐写为:mybatis-config.xml)
第三步:创建一个MybatisUtils工具类,(获得操作对象)
--需求:插入数据到数据库
第四步:创建一个映射接口
第五步:创建一个映射文件(.xml。文件名以接口名一致)
第六步:在主配置文件加载映射文件。
第七步:编写测试插入数据代码
2.3 配置步骤
2.3.1 下载并导入到项目中
下载地址:https://github.com/mybatis/mybatis-3
2.3.2 创建主配置文件 mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!-- dtd约束 --> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <!-- 根元素: 用于配置mybatis --> <configuration> <!-- 配置mybatis的运行环境 ,可以配置多个环境,但是一次只能使用一个 default属性 : 当前使用的环境 ,使用下面环境的id 即可 --> <environments default="mysql"> <!-- 环境配置 id 属性,就是当前环境的表示 --> <environment id="mysql"> <!-- 配置MyBatis事务管理器 type属性 : 事物类型 JDBC 使用事务(正常提交commit,异常回滚事务 rollback) 默认 MANAGED : 不使用事务 --> <transactionManager type="JDBC"/> <!-- 配置MyBatis的数据源 type : 配置连接池 POOLED :mybatis内置的一个连接池(默认) 后期都交给spring管理了,配置 dbcp连接池,阿里巴巴的 druid连接池 --> <dataSource type="POOLED"> <!-- 连接数据库的操作 --> <!-- 数据库驱动 --> <property name="driver" value="com.mysql.jdbc.Driver"/> <!-- 连接数据库的url --> <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/> <!-- 连接数据库账号 --> <property name="username" value="root"/> <!-- 连接数据库密码 --> <property name="password" value="1234"/> </dataSource> </environment> </environments> <!-- 配置映射文件 --> <mappers> <!-- 配置包扫描映射文件 --> <!-- <package name=""/> --> <!-- 配置单个映射文件 --> <mapper resource="org/mybatis/example/BlogMapper.xml"/> </mappers> </configuration>
2.3.3 创建MyBatisUtil工具类
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"; //jdk1.7以后在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; } }
2.3.4 创建数据库表对应的实体类pojo(javaBaen)
public class User { private Integer id; private String name; private String password; private Integer age; public User() { super(); } public User(Integer id, String name, String password, Integer age) { super(); this.id = id; this.name = name; this.password = password; this.age = 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; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", password=" + password + ", age=" + age + "]"; } }
2.3.5 创建操作接口
package cn.mybatis.mapper; import cn.mybatis.pojo.User; /* * 使用MyBatis的动态代理开发编写代码遵循四个原则 * 1.映射文件的namespace命名空间的值必须是对应接口的全限定名(包名+类名) 2.映射文件的对应功能 id值必须等于映射接口中方法的名称 3.映射文件的参数类型必须和接口中方法的参数类型一致 4.映射文件查询的返回结果类型必须和接口的方法的返回数据类型一致, DML操作返回的受影响的行数,除外 */ public interface UserMapper { int insertUserInfo(User u); }
2.3.6创建表对应的映射文件(后缀为.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"> <!-- 配置映射 namespace : 命名空间(和对应映射的接口的 全限定名一样) 通俗的讲就是给当前映射文件的唯一标识:起一个唯一的名字 --> <mapper namespace="cn.mybatis.pojo.UserMapper"> <!-- 新增操作 id: 当前功能的唯一标识,和接口方法同名 parameterType : 参数的类型 useGeneratedKeys:是否返回数据库生成的主键。默认为false keyProperty : 数据库主键对应java的pojo对象的属性 keyColumn : 数据表的主键列名 --> <insert id="insertUserInfo" parameterType="User" useGeneratedKeys="true" keyProperty="id" keyColumn="id" ></insert> </mapper>
2.3.7创建测试类测试
@Test public void testInsert() throws Exception { //1.创建SqlSession操作对象 SqlSession session = MyBatisUtil.openSession(); //2.创建UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); //3.创建用户对象 User user = new User(null, "乔峰", "qf", 30); //4.执行UserMapper的插入操作 userMapper.insertUserInfo(user); //5.提交事务 session.commit(); //6.关闭session session.close(); }
2.4Mybatis框架配置文件提示问题
MyBatis的配置文件使用dtd约束,如果在没有联网的情况想,默认开发者在使用时没有提示,这样不方便开发者编写代码。通过配置约束文件可让xml文件编写代码有提示
1.联网
2.手动管理DTD约束文件
3. log4j日志框架的配置
3.1什么是log4j
log4j是一个日志输出框架,就是用于输出日志的。Mybatis的日志输出是通过Log4J输出的。主流框架大部分都是Log4j输出的。Spring框架也可以通过Log4j输出日志!
Log4j提供了强大的日志输出的自定义功能。
1.通过级别输出日志 (调试、信息、警告、错误、致命异常)
2.可以指定输出到控制台,以及输出到文件。
3.可以设置输出的日志格式
所以学习LOG4J.需要学会自定义配置LOG4J的输出格式以及输出等级
3.2 下载
下载地址:http://logging.apache.org/log4j/1.2/
3.3 配置
导入jar包然后在src下创建一个log4j.propertis文件(文件名必须为log4j.propertis)
# Global logging configuration log4j.rootLogger=ERROR, stdout # MyBatis logging configuration... # log4j.logger.org.mybatis.example.BlogMapper=TRACE # 前缀(log4j.logger)+点(.)需要记录日志的命名空间 = 日志级别 log4j.logger.cn.mybatis.mapper=TRACE # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
4. 使用Mybatis完成CRUD(增删改查)操作
4.1 单行查询
<!-- 单行查询 resultType : 查询结果对应的封装的返回类型 --> <select id="selectByUserId" parameterType="integer" resultType="cn.mybatis.pojo.User"> select * from user where id = #{id} </select>
@Test public void testFindById() throws Exception { //1.创建SqlSession操作对象 SqlSession session = MyBatisUtil.openSession(); //2.创建UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); //3.执行单行查询操作 User user = userMapper.selectByPrimaryKey(1); System.out.println(user); // 4.关闭session session.close(); }
4.2 多行查询
<!-- 多行查询 resultType : 无论是多行查询还是单行查询,返回的结果类型都是对应的JavaBean的类型 --> <select id="selectAll" resultType="cn.mybatis.pojo.User"> select * from user </select>
@Test public void testFindAll() throws Exception { SqlSession session = MyBatisUtil.openSession(); // 创建UserMaper的代理对象 UserMapper mapper = session.getMapper(UserMapper.class); // 3.执行多行查询 List<User> users = mapper.selectAll(); for (User user : users) { System.out.println(user); } // 4.关闭session session.close(); }
4.3 删除操作
<!-- 删除操作 --> <delete id="deleteById" parameterType="integer"> delete from user where id = #{id} </delete>
// 删除操作 @Test public void testDelete() throws Exception { // 1.创建SqlSession操作对象 SqlSession session = MyBatisUtil.openSession(); // 2.创建UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); // 3.执行UserMapper的插入操作 userMapper.deleteById(3); // 4.提交事务 session.commit(); // 5.关闭session session.close(); }
4.4 修改操作
<!-- 修改操作 --> <update id="updateByUserId" parameterType="cn.mybatis.pojo.User"> update user set name = #{name},password = #{password},age = #{age} where id = #{id} </update>
// 修改操作 @Test public void testUpdate() throws Exception { // 1.创建SqlSession操作对象 SqlSession session = MyBatisUtil.openSession(); // 2.创建UserMapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); // 3.创建用户对象 User user = new User(2, "李四", "dy", 25); // 4.执行UserMapper的插入操作 userMapper.updateUserInfo(user); // 5.提交事务 session.commit(); // 6.关闭session session.close(); }
5.ResultMap 手动映射
MyBatis的查询结果集都是自动映射封装的,单行查询将数据库一条数据封装成对应的Java对象。多行查询,先将每一行封装成对象,再将每个对象添加到集合中,最后返回一个List集合对象。但是这必须保证查询结果集和pojo对象的属性名相同,否则无法自动封装。那么如何实现查询结果集名称和pojo对象属性不同的映射封装?
方法:使用手动映射封装 <ResultMap>标签
<?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"> <!-- 映射配置 namespace : 命名空间,通俗讲,每个映射文件唯一的标识名称 --> <mapper namespace="cn.mybatis.mapper.UserMapper"> <!-- resultType : 自动映射 resultMap : 手动映射,值 自定义对应手动映射标签的 id的值 注意:自动映射和手动映射二选一,不能同时使用 --> <select id="findByUserId" parameterType="Integer" resultMap="user_map"> <!-- #{} OGNL表达式语言 --> select id u_id,name u_name,password u_password ,age u_age from user where id = #{id} </select> <!-- 手动映射 type :需要手动映射的数据类型 id :唯一标识 --> <resultMap type="User" id="user_map"> <!-- 主键列映射 <id column="" property="" javaType="" jdbcType=""/> column :结果的列名 property:domain对象的对应的属性名 javaType :domian对象的属性的类型(可选,默认自动关联) jdbcType :结果集列类型(可选,默认自动关联) --> <id column="u_id" property="id" javaType="Integer" jdbcType="INTEGER"/> <!-- 非主键列映射 <result column="" property="" javaType="" jdbcType=""/> column :结果的列名 property:domain对象的对应的属性名 javaType :domian对象的属性的类型(可选,默认自动关联) jdbcType :结果集列类型(可选,默认自动关联) --> <result column="u_name" property="name"/> <result column="u_age" property="age"/> <result column="u_password" property="password"/> </resultMap> </mapper>
6. 主配置文件细节配置及常用标签
6.1配置细节
<environments>:环境集标签,就是用于配置数据库的连接信息的
<environment>:用于配置具体环境参数
<transactionManager>:配置使用的事务类型,JDBC
<dataSource>:配置数据源的参数,POOLED
具体参数参看PooledDataSource的set方法
<property>:配置属性
<mappers>:配置映射文件信息的
<mapper class|resource>:配置具体指定的mapper文件
class:配置使用注解时指定有注解的映射接口
resource:指定映射文件
<properties>:mybatis对propertis文件的支持
<typeAliases>:用于配置别名
<typeHandlers>:用于配置自定义类型处理器.
<settings>:配置Mybatis的默认设置的.
6.2 总配置文件的标签顺序
<!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次
6.3 别名typeAliases标签
配置了别名之后可以使用别名代替限定名
MyBatis框架中有两种别名机制,一种是自定义别名,一种是内置别名
自定义别名
<!-- 别名设置 -->
<typeAliases>
<!-- 设置单个类的别名
type :要设置别名的全限定名
alias :别名 (一般设成简单类名)
-->
<typeAlias type="cn.mybatis.pojo.User" alias="User"/>
</typeAliases>
内置别名,即MyBatis框架自带别名
6.4 properties标签 读取配置文件
一般开发会将单独的数据库连接字符串配置到一个独立的 以 .properties 的配置文件中。
Mybaits框架中配置文件 的 <properties>标签可以读取配置文件中的内容。并可以使用${}的语法设置给框架的数据库连接操作代码。
1.在src下面创建一个db.properties数据库连接配置文件
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis jdbc.username=root jdbc.password=1234
2.在mybatis-config.xml主配置文件中配置<properties>标签读取配置文件
<!-- 读取db.properties数据库配置文件,读取以后再下面链接数据库的配置中就可以使用
${配置文件key} 获取对应的数据库连接相关信息
-->
<properties resource="db.properties"/>
<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>
6.5 settings标签(设置默认配置)
Mybatis默认设置了很多默认配置.有时候,我们需求与默认的配置的参数不一样,我们就需要修改这些默认配置的参数.
常用的如:Mybatis已经对骆驼命名法的支持(数据库字段名单词间一般用_分隔,java用驼峰,开启之后可以自动转换),默认是不开启的.可以通过mapUnderscoreToCamelCase参数设置为true支持
<!-- 配置默认的参数 --> <settings> <!-- 默认支持骆驼命名法 --> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
7.MyBatis的注解开发
MyBatis的映射配置除了使用xml配置以外,还支持注解配置sql语句。MyBatis的注解开发更简洁,只需要将对应的SQL语句的注解标注对应的功能方法上即可,直接连XxxMapper.xml映射文件都可以省略。
MyBatis提供了下面注解进行映射文件配置
@Select 查询数据注解
@Insert 插入数据注解
@Delete 删除数据注解
@Update 修改数据注解
@Options 选项配置
@Results 手动映射配置
@Result : @results中的具体的某一列的映射信息配置
使用注解开发要先在主配置文件中指定使用注解的接口
<!-- 映射文件的配置 -->
<mappers>
<!-- 直接配置Mapper接口,映射接口的全限定名 -->
<mapper class="cn.mybatis.mapper.UserMapper"/>
</mappers>
8.方法的多参数传递
Mybatis默认情况下是不支持传入多个参数的.只能传入一个参数.
方案1:将这些参数封装到一个对象里面(JavaBean/Map),再传入.
方案2:给参数设置一个@Param注解支持,而且多参数的类型要统一
User login1(User user); User login2(Map<String, Object> map); User login3(@Param("username")String name,@Param("pwd")String password);
9.#{}与${}的区别
#{}基于JDBC的PreparedStatement类,SQL语句参数使用 ?占位符,在运行阶段动态设置参数,但是 ?不能作为表名.
预编译语句对象的SQL语句只能 操作 DML和DQL 语句,不能操作DDL语句
1.#{}表示设置预编译的参数,就是?的参数,所以如果要不固定的表名不能使用#{},只能使用${}
2.${}直接把参数拼接到SQL语句中.而#{]是使用?来代替. 所以${}是不安全的.
3.${}只能获得参数池的值,而#{}可以获得方法的参数值,也可以获得参数池的值,如果使用${}获得参数的值,这个参数必须要加上@Param
注:如果非必要情况,不要使用${}( ?不能作为表名,所以如果操作的涉及表名这些非参数的 数据时,需要使用${})