实战项目完成代码:MybatisTest_GitHub
1.简介
- 持久层框架,java编写
- 它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程
- 使用ORM思想,ORM:Object Relational Mapping 对象关系映射,就是将数据库表和实体类做映射,操作实体类就能实现操作数据库表。
2. 环境搭建
- 创建父工程mybatistest,删除不需要的包(src)并添加坐标,修改pom文件
<dependencies>
<!--mybatis框架-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--数据库连接(选择适合自己数据库)-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<!--日志信息(为了能够看到更详细的信息,不加也行那样只会出现结果)-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
- 准备数据库资源
create database mybatistest;
use mybatistest;
drop table if exists `user`;
create table `user`(
`id` int(10) primary key auto_increment,
`name` varchar(20),
`age` int(3)
);
insert into `user`(`name`,`age`) values('小明',22);
insert into `user`(`name`,`age`) values('小红',25);
3. day1——入门
我们已经完成了父工程的搭建,接下来我们要正式开始第一天的学习
3.1 子模块准备工作
- 在父工程下面,创建子工程day1,因为我们在父工程中导入了坐标,所有子工程不需要导入
- 导入日志配置文件 log4j.properties 该文件不用特别关系,直接创建复制粘贴即可 放在resources文件夹下
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:\axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
- 创建实体类com.lois.domain.User,在简介中我们说了,mybatis是ORM思想,所以我们需要创建实体类映射数据库表,注:自己生产set和get以及toString方法
public class User implements Serializable {
private Integer id;
private String name;
private Integer age;
}
3.2 快速入门
在快速入门阶段,我们写一个最简单的例子——查询所有用户
- 创建com.lois.dao.UserDao接口,编写接口方法
public interface UserDao {
/**
* 查询所有用户
* @return
*/
public List<User> findAll();
}
- 创建映射文件com/lois/dao/UserDao.xml,该文件位于resources文件夹下,注:路径一定要与第一步dao一致
<?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="com.lois.dao.UserDao">
<select id="findAll" resultType="com.lois.domain.User">
select * from user;
</select>
</mapper>
- 在resources文件夹下创建SqlMapConfig.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">
<configuration>
<environments default="mysql">
<!--配置mysql环境-->
<environment id="mysql">
<!--配置事务类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)需要自己修改-->
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatistest?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1234567"/>
</dataSource>
</environment>
</environments>
<!--指定映射文件-->
<mappers>
<mapper resource="com/lois/dao/UserDao.xml"/>
</mappers>
</configuration>
- 接下来我们就可以开始测试了,在Test包下创建com.lois.test.MybatisTest测试类
public class MybatisTest {
@Test
public void test1() throws IOException {
//1.获取工厂图纸(配置信息)
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.招募工人(创建构建者)
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//3.给工人图纸建造工厂(构建者构建工厂对象)
SqlSessionFactory factory = builder.build(in);
//4.构建产品流水线(打开自动提交事务)
SqlSession session = factory.openSession(true);
//5.根据产品设计图生产出产品(动态代理)
UserDao userDao = session.getMapper(UserDao.class);
//6.使用产品
List<User> users = userDao.findAll();
for (User user :
users) {
System.out.println(user);
}
//7.回收(释放资源)
session.close();
in.close();
}
}
- 运行测试类,控制台输出一下内容
2019-08-11 09:21:25,572 0 [ main] DEBUG ache.ibatis.logging.LogFactory - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
2019-08-11 09:21:25,844 272 [ main] DEBUG source.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
2019-08-11 09:21:25,844 272 [ main] DEBUG source.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
2019-08-11 09:21:25,844 272 [ main] DEBUG source.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
2019-08-11 09:21:25,844 272 [ main] DEBUG source.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
2019-08-11 09:21:25,969 397 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Opening JDBC Connection
2019-08-11 09:21:26,454 882 [ main] DEBUG source.pooled.PooledDataSource - Created connection 728258269.
2019-08-11 09:21:26,454 882 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2b6856dd]
2019-08-11 09:21:26,456 884 [ main] DEBUG com.lois.dao.UserDao.findAll - ==> Preparing: select * from user;
2019-08-11 09:21:26,487 915 [ main] DEBUG com.lois.dao.UserDao.findAll - ==> Parameters:
2019-08-11 09:21:26,545 973 [ main] DEBUG com.lois.dao.UserDao.findAll - <== Total: 2
User{id=1, name='小明', age=22}
User{id=2, name='小红', age=25}
2019-08-11 09:21:26,548 976 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2b6856dd]
2019-08-11 09:21:26,549 977 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2b6856dd]
2019-08-11 09:21:26,549 977 [ main] DEBUG source.pooled.PooledDataSource - Returned connection 728258269 to pool.
4. 思考
mybatis的入门其实比较简单,只有四步:
- 导包和创建实体类
- 编写dao接口和映射文件
- 编写工厂图纸配置文件(SqlMapConfig.xml)
- 编写测试类
那么下面我们就来详细了解一下这四步
4.1 导包和实体类
导包我就不再说了,聊一聊实体类。mybatis是ORM思想,所以实体类其实就像是数据库中的一个表,表中的字段就对应着实体类的属性,一个实体类的实例就对应着数据库表中的一行数据,当我们修改实体类的实例时再传给mybatis,mybatis会将我们修改的信息同步到数据库表中。这也就实现了我们修改实体类就是修改数据库表。当然这里要注意,实体类的属性类型要与数据库中字段的类型匹配。实体类还有一种用法,就是实体类中包含另外一种实体类,这是为什么呢?其实这是为了实现数据库中的关系:一对一,一对多,多对一,多对多。这个问题我们在后面章节再讨论。
4.2 dao接口和映射文件
使用mybatis框架,我们就不用自己写持久层实现类,但是我们还是要写持久层接口,因为我们要告诉mybatis我们需要什么样的方法,我们告诉了mybatis我们需要的方法,但是接口只能提供哪些信息?方法名,返回类型,参数列表。这些信息是不够的,还需要sql语句,所以就有映射文件,这个映射文件映射的就是dao接口中的方法,映射文件告诉mybatis接口中方法的sql语句,这样mybatis就能帮我们完成dao操作。
dao接口没有什么好说的,就跟以前我们不用框架一样,那我们就要来聊一聊这个映射文件。
映射文件要求:
- 创建位置:必须和持久层接口在相同的包中。
- 名称:必须以持久层接口名称命名文件名以Dao或Map结尾,扩展名是.xml,例:接口为UserDao,那么映射文件名称应该为UserDao.xml或UserMap.xml
映射文件内标签:
- mapper标签
- namespace 属性:指定映射文件映射的dao接口,全类名
- resultMap 结果映射:用于当查询结果与实体类中无法匹配时,从而自定义对应关系,使其能够进行封装
- id 属性:唯一标识,能够在select标签中使用
- type 属性:指定实体类的全类名
- 子标签 id 标签:用于指定主键字段
- 子标签 result 标签:用于指定非主键字段
- 子标签属性 column:用于指定数据库列名
- 子标签属性 property:用于指定实体类属性名称
- select、update、insert、delete标签:对应增删查改
- id 属性:指定映射dao接口的哪个方法,方法名
- parameterType 属性:参数类型,基本类型和String可以直接写类型名称,其他要写全类名
- resultType 属性:返回类型,基本类型和String可以直接写类型名称,其他要写全类名 。实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。
- resultMap 属性:当查询结果无法与实体类匹配时,我们就能使用上面resultMap定义的映射,内容填写映射id
- 标签内容:sql语句+占位符
- 占位符
- #{}:表示一个占位符号(常用)
通过#{}可以实现 preparedStatement 向占位符中设置值,自动进行 java 类型和 jdbc 类型转换,#{}可以有效防止 sql 注入。 #{}可以接收简单类型值或实体类属性名称。 如果 parameterType 传输单个简单类型值,#{}括号中可以是 value 或其它名称(名称随意)。如果parameterType传递实体类,#{}括号中可以是实体类属性名称 - ${}:表示拼接sql串(不常用)
通过${}可以将 parameterType 传入的内容拼接在 sql 中且不进行 jdbc 类型转换, ${}可以接收简单类型值或实体类属性名称,如果 parameterType 传输单个简单类型值,${}括号中只能是 value。
- #{}:表示一个占位符号(常用)
- 占位符
4.3 SqlMapConfig.xml的配置内容
-
configuration 标签:外部总标签,没什么好说的
- properties 标签:用来加载一些配置信息
- resource 属性:指定加载信息的文件名称(该文件在resources文件夹下).properties类型的文件(key=value类型)
- url 属性:使用url路径访问加载文件,文件类型同上
- property 子标签:只是将上面的加载文件中内容下在标签属性中(意义不大,不常用)
- name 属性:对应上面加载文件的key
- value 属性:对应上面加载文件的value
- 效果:能通过 ${key} 来获取加载文件中key对应的value的值,我们一般把数据源的信息放在外部加载文件中,在数据源中通过${key}来获取,这样以后不用动数据源那块,直接修改外部加载文件就行。
- typeAliases 标签:类型别名,让我们配置中不用写全类名,这个设置不只在SqlMapConfig.xml文件中有效,在dao映射文件中也有效
- typeAlias 子标签:单个别名设置
- alias 属性:别名
- type 属性,设置别名的全类名
- package 标签:批量设置别名,扫描整个包下的类,别名为类名(首字母大写或小写都可以)
- name 属性:需要扫描的包路径
- typeAlias 子标签:单个别名设置
- properties 标签:用来加载一些配置信息
-
mappers标签:配置dao映射文件位置
- mapper 子标签:单个设置映射文件位置
- resource 属性:使用相对于类路径,查找dao映射文件
- <mapper resource=“com/lois/dao/UserDao.xml”/>
- class 属性:使用 mapper 接口类路径
- <mapper class=“com.lois.dao.UserDao”/>
- 注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。
- resource 属性:使用相对于类路径,查找dao映射文件
- package 标签:注册指定包下的所有 mapper 接口
- <package name=“com.itcast.dao”>
- 注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。
- mapper 子标签:单个设置映射文件位置
4.4 编写测试类
在测试类中,我已经在注释中写了好记的7步,其实这里使用了两种模式:构建者模式和工厂模式。在搭建工厂时我们使用了构建者模式,在生产时我们使用了工厂模式。那么我们为什么要使用这么多步骤呢?为什么不一步到位?这是因为我们使用mybatis框架让它给我们实现dao,每多一个步骤,就会给mybatis更大的灵活性,多一步选择,这是很有好处的。mybatis在第5步生产产品时使用了动态代理,增强了我们写的dao接口类,实现了接口中的方法,从而使我们能够不写dao类。
5 作业
如果你看懂了上面的思考,那么你就应该能写出基本的增删查改,请自行尝试,当然上面思考的内容有点多,我们在后面的章节中还会继续讲解,没有看懂也没事。
下一章:(二)Mybatis增删查改、动态SQL语句、多表操作(简单易懂,图文教学,整套实战)
相关内容:
(一)初见MyBatis,快速入门以及配置文件映射文件讲解(构建思路讲解,图文教学,整套实战)