Java框架学习:MyBatis之MyBatis入门、优化配置、Mapper映射文件

本文介绍了MyBatis作为ORM框架的基本概念,详细阐述了MyBatis的入门步骤,包括创建第一个MyBatis程序,涉及数据库表user的建立、配置文件、实体类、映射文件的创建。接着讨论了MyBatis的优化配置,如从properties文件读取数据库连接参数和日志配置。最后,讲解了Mapper映射文件的使用,展示了增删改查的Sql语句配置及其在实际操作中的应用。
摘要由CSDN通过智能技术生成

ORM

对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。

具体表现:
O - Java对象
R - 数据库表
M - 映射文件
一个Java类对应数据库中的一张表;一个Java对象对应数据库表中的一条数据;Java对象的属性对应数据库表的列。
而这种对应关系通过映射(Mapping)来实现

MyBatis入门

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。

第一个MyBatis程序

存在一张数据库表user,相当于ORM中的“R”,建表语句如下:

CREATE TABLE `user` (
  id int(11) NOT NULL AUTO_INCREMENT,
  username varchar(20) DEFAULT NULL,
  password varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

第一步需要导入依赖

<!--mybatis的jar包-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<!--数据库驱动jar mysql-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.18</version>
</dependency>

第二步创建一个配置文件"mybatis-config.xml"

<?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">
<configuration>
    <environments default="development">
        <environment id="development">
            <!--事务管理,采用JDBC-->
            <transactionManager type="JDBC"/>
            <!--mybatis提供的简单数据源,也可以取值为JNDI,让容器管理数据源-->
            <dataSource type="POOLED">
                <!--数据库连接的参数,任何数据库框架都需要以下参数-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_db?serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="123"/>
            </dataSource>
        </environment>
    </environments>
    
    <mappers>
        <mapper resource="com/young/mapper/UserMapper.xml"/>
    </mappers>
</configuration>
mybatis-config.xml映射文件解析:
XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务
管理器(TransactionManager)。
environment元素体中包含了事务管理和连接池的配置。在environments标签中设置default属性指定默认使用的数据库连接环境(environment)
mappers 元素则包含了一组映射器(mapper),这些映射器的 XML 映射文件包含了 SQL 代码和映射定义信息。

创建实体类User,相当于ORM中的“O”

public class User {
	//注意实体类中的属性名称需要与数据库表中列名一一对应
    private Integer id;
    private String username;
    private String password;

   //以下省略了所有成员变量的get和set方法......
   
}

创建文件"UserMapper.xml"映射文件作为ORM中的“M”

<?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:命名空间,相当于package-->
<!--Sql语句编写在Mapper配置文件中被程序读取,
程序通过namespace.sqlid确认唯一的sql的引用,namespace通常和文件名保持一致-->
<mapper namespace="com.young.mapper.UserMapper">
    <!--查询标签,属性id是sql在本文件中的唯一标识-->
    <!--resultType是mybatis中的结果集映射,不管结果是一条数据还是多条数据resultType都配置为单条数据的类型-->
    <select id="selectAll" resultType="com.young.model.User">
        select * from user
    </select>
</mapper>

测试类:

import com.alibaba.fastjson.JSON;
import com.young.model.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class TestMapper {
    @Test
    public void testMapper() throws IOException {
        //获取字节输入流,用于读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        //通过session工厂构建器构建session工厂
        //SqlSessionFactory可以获取SqlSession对象,只能是唯一存在的
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //SqlSession可以类比为javaWeb中的session,表示程序和数据库的一次交互
        //可以与数据库建立连接并执行查询、更新等语句
        //此对象需要每次操作都是一个新的对象,不能放在全局供多个线程共同使用
        SqlSession session = sessionFactory.openSession();
        //执行Sql语句,传递Sql的唯一标识,即namespace.Sqlid
        //selectList将查询的结果封装为一个List
        //mybatis会将数据库中查询出的列和java实体类的属性一一对应,否则该属性不被赋值,如果名称不一致,可以在配置文件中配置或者使用别名
        List<User> list = session.selectList("com.young.mapper.UserMapper.selectAll");
        System.out.println(JSON.toJSONString(list,true));
    }
}
每个基于MyBatis的应用都是以一个SqlSessionFactory的实例为核心的,SqlSessionFactoryBuilder可以从XML配置文件或一个预先配置的
Configuration实例来构建出SqlSessionFactory实例。MyBatis提供了一个Resources工具类,使得从类路径或其它位置加载资源文件更加容易。

SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了SqlSessionFactory,就不再需要它了。 因此SqlSessionFactoryBuilder实例的最佳作用域
是方法作用域(也就是局部方法变量)。在程序中最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。 
SqlSessionFactory
SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,不能丢弃它或重新创建另一个实例。 使用SqlSessionFactory的最佳实践是
在应用运行期间不要重复创建多次。因此SqlSessionFactory的最佳作用域是应用作用域。 可以使用单例模式来做到这一点。
SqlSession
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。也绝不能将 SqlSession 实例的引用放在任何类型的托
管作用域中,比如Servlet框架中的HttpSession。如果你现在正在使用一种Web框架,考虑将SqlSession放在一个和HTTP请求相似的作用域中。
换句话说,每次收到HTTP请求,就可以打开一个SqlSession,返回一个响应后,就关闭它。这个关闭操作很重要,为了确保每次都能执行关闭操作,
你应该把这个关闭操作放到 finally 块中。

maven默认不会将src/main/java中的xml文件编译,在pom.xml中增加配置

<build>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.xml</include>
            </includes>
        </resource>
    </resources>
</build>

优化配置

读取配置文件获取数据库连接的参数

在配置文件"mybatis-config.xml"中,数据库连接的参数可以从properties文件中获取
db.properties配置文件

db.url=jdbc:mysql://localhost:3306/mybatis_db?serverTimezone=UTC
db.username=root
db.password=123
db.driverClassName=com.mysql.jdbc.Driver

在mybatis-config.xml文件中增加如下配置来读取配置文件

<!--ref代表读取网络文件-->
<!--resource属性代表读取本地文件,默认从classes目录下读取-->
<properties resource="db.properties"/>

mybatis-config.xml文件中修改数据库连接的参数

<dataSource type="POOLED">
    <!--使用${}读取配置文件中的值-->
    <property name="driver" value="${db.driverClassName}"/>
    <property name="url" value="${db.url}"/>
    <property name="username" value="${db.username}"/>
    <property name="password" value="${db.password}"/>
</dataSource>
日志配置

MyBatis框架在执行时是黑箱操作,MyBatis框架记录了日志,只需要增加jar包,编写配置文件就可以展示执行过程中的信息。
导入jar包

 <!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
	<groupId>log4j</groupId>
	<artifactId>log4j</artifactId>
	<version>1.2.17</version>
</dependency>

配置文件log4j.properties

#USE THIS SETTING FOR OUTPUT MYBATIS`s SQL ON THE CONSOLE
log4j.rootLogger=debug, Console,E

#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
#log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.appender.Console.layout.ConversionPattern=[ %l ] %d{yyyy/MM/dd HH:mm:ss} %-5p [%c{1}] - %l - %m%n

### \u4FDD\u5B58\u5F02\u5E38\u4FE1\u606F\u5230\u5355\u72EC\u6587\u4EF6 ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File = error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

再运行程序就会输出日志,比如执行的Sql语句,参数以及查询的数据条数

[ org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ] 2020/05/22 16:23:29 DEBUG [selectAll] - org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) - ==>  Preparing: select * from user 
[ org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ] 2020/05/22 16:23:29 DEBUG [selectAll] - org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) - ==> Parameters: 
[ org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ] 2020/05/22 16:23:29 DEBUG [selectAll] - org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) - <==      Total: 2

Mapper映射文件

在UserMapper.xml文件中配置增删改查的Sql语句

<?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="com.young.mapper.UserMapper">
    <!--查询所有数据-->
    <select id="selectAll" resultType="com.young.model.User">
        select * from user
    </select>
    <!--根据id查询单条数据-->
    <select id="selectById" resultType="com.young.model.User">
        select * from user where id=#{id}
    </select>
    <!--更新数据-->
    <update id="update" parameterType="com.young.model.User">
        update user set username=#{username} where id=#{id}
    </update>
    <!--插入数据-->
    <insert id="insert" parameterType="com.young.model.User">
        insert into user values(#{id},#{username},#{password})
    </insert>
    <!--删除数据-->
    <delete id="delete">
        delete from user where id=#{id}
    </delete>
</mapper>

测试类
测试根据id查询单条数据
在其他测试代码中省略获取SqlSession实例的过程

@Test
public void testMapper() throws IOException {
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    SqlSession session = sessionFactory.openSession();
  	User user = session.selectOne("com.young.mapper.UserMapper.selectById",1);
    System.out.println(JSON.toJSONString(user));
}

测试更新数据

User user = new User();
user.setId(1);
user.setUsername("abc");
//返回影响的行数
session.update("com.young.mapper.UserMapper.update", user);
//MyBatis默认为手动提交,所以对于增删改操作需要调用commit()方法
session.commit();

测试插入数据

User user = new User();
user.setId(5);
user.setPassword("555");
user.setUsername("eee");
//返回影响的行数
session.insert("com.young.mapper.UserMapper.insert", user);
session.commit();

插入数据时的日志记录
根据日志可以看出,他会根据根据参数的类型和名称实现注入

[ org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ] 2020/05/22 16:31:49 DEBUG [insert] - org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) - ==>  Preparing: insert into user values(?,?,?) 
[ org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ] 2020/05/22 16:31:49 DEBUG [insert] - org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) - ==> Parameters: 5(Integer), eee(String), 555(String)
[ org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) ] 2020/05/22 16:31:49 DEBUG [insert] - org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:159) - <==    Updates: 1
[ org.apache.ibatis.transaction.jdbc.JdbcTransaction.commit(JdbcTransaction.java:70) ] 2020/05/22 16:31:49 DEBUG [JdbcTransaction] - org.apache.ibatis.transaction.jdbc.JdbcTransaction.commit(JdbcTransaction.java:70) - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@467aecef]

测试删除数据

//返回影响的行数
session.delete("com.young.mapper.UserMapper.delete", 5);
session.commit();
resultType:表示执行Sql语句返回结果的类型
	selectList()方法会返回一个List集合,MyBatis会将查询出的每一条数据封装为User对象并存入List集合。
	selectOne()方法会返回一个resultType属性指定类的对象,MyBatis会将查询出单条数据封装为User对象。
	如果查询出多条数据却使用了selectOne()方法,会出现异常。
	如果返回结果为自定义类型,结果的列明需要和自定义类的setXxx()方法中"Xxx"名称保持一致。如setUsername(),那么列明就为"username"
parameterType:表示输入参数的类型
	使用#{}作为参数的占位符
	如果数据类型为基本数据类型(包括包装类)以及String,可以不用设置输入参数类型,MyBatis会实现自动注入
	如果指定输入参数的类型为自定义类,如User类,那么User类中的属性名需要和#{}中的参数名一致
	
	区分${}和#{}
	${}在mybatis-config.xml中可以读取配置文件中的内容,也可以用在mapper.xml中,但是慎用!
	${}值只可以为value,且只会将值直接拼接在sql语句中,无任何处理,如下所示:
	<select id="selectByName" resultType="com.young.model.User">
        select * from user where username=${value}
    </select>
    在运行时,Sql语句为:"select * from user where username=aaa";当值为String类型时,不会给值拼接引号。
    而#{}中的值为列名,比如${id}、${username},且将值拼接在sql语句中时会拼接引号
    在运行时,Sql语句为:"select * from user where username='aaa'";
    所以如果要使用${},需要在传递参数时加上引号,而且使用${}时如果没有拦截器存在发生Sql注入的风险。	

在UserMapper.xml文件中,对于resultType以及parameterType每次都要写完整的包名及类名,可以使用别名来简化书写
在mybatis-config.xml文件中增加如下配置

<typeAliases>
	<!--只能对单个类进行别名设置-->
	<typeAlias type="com.young.model.User" alias="User"/>
    <!--如果包中类过多时,可以使用<package>标签对当前包以及子包中的所有类进行别名的设置-->
    <!--默认包下的类名就是别名,不区分大小写-->
    <!--<package name="com.young.model"/>-->
</typeAliases>
当<typeAlias>标签进行别名设置时,在在UserMapper.xml文件中Sql语句标签如下:
<select id="selectAll" resultType="User">
	select * from user
</select>
当<package>标签进行别名设置时,在在UserMapper.xml文件中Sql语句标签如下:
<select id="selectAll" resultType="user">
	select * from user
</select>
resultType的值可以为"user",也可以为"User"。

需要注意<configuration>节点中的内容顺序,否则会报错。顺序如下:
properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?"。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值