mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。
采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。
下面的是使用 jdbc 的原始方法(未经封装)实现了查询数据库表记录的操作。
public static void main(String[] args) {
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//通过驱动管理类获取数据库链接
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8", "root", " root");
//定义 sql 语句 ?表示占位符
String sql = "select * from user where username = ?";
//获取预处理 statement
preparedStatement = connection.prepareStatement(sql);
//设置参数,第一个参数为 sql 语句中参数的序号(从 1 开始),第二个参数为设置的参数值
preparedStatement.setString(1, "王五");
//向数据库发出 sql 执行查询,查询出结果集
resultSet = preparedStatement.executeQuery();
//遍历查询结果集
while (resultSet.next()) {
System.out.println(resultSet.getString("id") + " "+resultSet.getString(" username"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//释放资源
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
2、Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java代码。
3、使用 preparedStatement 向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能多也可能少,修改 sql 还要修改代码,系统不易维护。
4、对结果集解析存在硬编码(查询列名),sql 变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成 pojo 对象解析比较方便。
如果使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.5version>
dependency>
pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.keafmdgroupId>
<artifactId>day01_eesy_01mybatisartifactId>
<version>1.0-SNAPSHOTversion>
<packaging>jarpackaging>
<dependencies>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.5version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.49version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>1.2.17version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13version>
<scope>testscope>
dependency>
dependencies>
project>
创建个数据库eesy_mybatis
,入门案例中只使用到了user表。
sql文件:
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL auto_increment,
`username` varchar(32) NOT NULL COMMENT '用户名称',
`birthday` datetime default NULL COMMENT '生日',
`sex` char(1) default NULL COMMENT '性别',
`address` varchar(256) default NULL COMMENT '地址',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (41,'老王','2018-02-27 17:47:08','男','北京'),(42,'小二王','2018-03-02 15:09:37','女','北京金燕龙'),(43,'小二王','2018-03-04 11:34:34','女','北京金燕龙'),(45,'传智播客','2018-03-04 12:04:06','男','北京金燕龙'),(46,'老王','2018-03-07 17:37:26','男','北京'),(48,'小马宝莉','2018-03-08 11:44:00','女','北京修正');
DROP TABLE IF EXISTS `account`;
CREATE TABLE `account` (
`ID` int(11) NOT NULL COMMENT '编号',
`UID` int(11) default NULL COMMENT '用户编号',
`MONEY` double default NULL COMMENT '金额',
PRIMARY KEY (`ID`),
KEY `FK_Reference_8` (`UID`),
CONSTRAINT `FK_Reference_8` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `account`(`ID`,`UID`,`MONEY`) values (1,41,1000),(2,45,1000),(3,41,2000);
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`ID` int(11) NOT NULL COMMENT '编号',
`ROLE_NAME` varchar(30) default NULL COMMENT '角色名称',
`ROLE_DESC` varchar(60) default NULL COMMENT '角色描述',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `role`(`ID`,`ROLE_NAME`,`ROLE_DESC`) values (1,'院长','管理整个学院'),(2,'总裁','管理整个公司'),(3,'校长','管理整个学校');
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`UID` int(11) NOT NULL COMMENT '用户编号',
`RID` int(11) NOT NULL COMMENT '角色编号',
PRIMARY KEY (`UID`,`RID`),
KEY `FK_Reference_10` (`RID`),
CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `role` (`ID`),
CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into `user_role`(`UID`,`RID`) values (41,1),(45,1),(41,2);
User类:
package com.keafmd.domain;
import java.util.Date;
/**
* Keafmd
*
* @ClassName: User
* @Description: user实体类
* @author: 牛哄哄的柯南
* @date: 2021-02-06 19:26
*/
public class User {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", birthday=" + birthday +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
'}';
}
}
IUserDao:
package com.keafmd.dao;
import com.keafmd.domain.User;
import java.util.List;
/**
* Keafmd
*
* @ClassName: IUserDao
* @Description: 用户的持久层接口
* @author: 牛哄哄的柯南
* @date: 2021-02-06 19:29
*/
public interface IUserDao {
/**
* 查询所有操作
* @return
*/
List<User> findAll();
}
IUserDao.xml:
<mapper namespace="com.keafmd.dao.IUserDao">
<select id="findAll" resultType="com.keafmd.domain.User">
select * from user
select>
mapper>
SqlMapConfig.xml:
<configuration>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC">transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/eesy_mybatis"/>
<property name="username" value="root"/>
<property name="password" value="18044229"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/keafmd/dao/IUserDao.xml">mapper>
mappers>
configuration>
log4j.properties:
# 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
MybatisTest:
package com.keafmd.test;
import com.keafmd.dao.IUserDao;
import com.keafmd.domain.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 javax.annotation.Resource;
import java.io.InputStream;
import java.util.List;
/**
* Keafmd
*
* @ClassName: MybatisTest
* @Description: 测试类
* @author: 牛哄哄的柯南
* @date: 2021-02-06 19:55
*/
public class MybatisTest {
/**
* 入门案例
* @param args
*/
public static void main(String[] args) throws Exception{
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产SqlSession对象
SqlSession session = factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println(user);
}
//6.释放资源
session.close();
in.close();
}
}
2021-02-06 20:50:29,169 0 [ main] DEBUG ache.ibatis.logging.LogFactory - Logging initialized using 'class org.apache.ibatis.logging.log4j.Log4jImpl' adapter.
2021-02-06 20:50:29,224 55 [ main] DEBUG source.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
2021-02-06 20:50:29,224 55 [ main] DEBUG source.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
2021-02-06 20:50:29,224 55 [ main] DEBUG source.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
2021-02-06 20:50:29,225 56 [ main] DEBUG source.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
2021-02-06 20:50:29,523 354 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Opening JDBC Connection
2021-02-06 20:50:30,265 1096 [ main] DEBUG source.pooled.PooledDataSource - Created connection 738433734.
2021-02-06 20:50:30,265 1096 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2c039ac6]
2021-02-06 20:50:30,304 1135 [ main] DEBUG om.keafmd.dao.IUserDao.findAll - ==> Preparing: select * from user
2021-02-06 20:50:30,368 1199 [ main] DEBUG om.keafmd.dao.IUserDao.findAll - ==> Parameters:
2021-02-06 20:50:30,494 1325 [ main] DEBUG om.keafmd.dao.IUserDao.findAll - <== Total: 6
User{
id=41, username='老王', birthday=Tue Feb 27 17:47:08 CST 2018, sex='男', address='北京'}
User{
id=42, username='小二王', birthday=Fri Mar 02 15:09:37 CST 2018, sex='女', address='北京金燕龙'}
User{
id=43, username='小二王', birthday=Sun Mar 04 11:34:34 CST 2018, sex='女', address='北京金燕龙'}
User{
id=45, username='传智播客', birthday=Sun Mar 04 12:04:06 CST 2018, sex='男', address='北京金燕龙'}
User{
id=46, username='老王', birthday=Wed Mar 07 17:37:26 CST 2018, sex='男', address='北京'}
User{
id=48, username='小马宝莉', birthday=Thu Mar 08 11:44:00 CST 2018, sex='女', address='北京修正'}
2021-02-06 20:50:30,497 1328 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2c039ac6]
2021-02-06 20:50:30,499 1330 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@2c039ac6]
2021-02-06 20:50:30,499 1330 [ main] DEBUG source.pooled.PooledDataSource - Returned connection 738433734 to pool.
Process finished with exit code 0
把1和2保持一致,我的上面是1.8,下面就改成8。