Mybatis(一)入门程序
-
对原生态JDBC问题总结
-
原生JDBC代码
-
package com.utils;
-
-
import java.sql.Connection;
-
import java.sql.DriverManager;
-
import java.sql.PreparedStatement;
-
import java.sql.ResultSet;
-
import java.sql.SQLException;
-
-
/**
-
* @ClassName: JdbcTest
-
* @Description: TODO(原始的JDBC操作数据库)
-
* @author warcaft
-
* @date 2015-6-27 下午3:31:22
-
*
-
*/
-
public class JdbcTest {
-
public static void main(String[] args) {
-
-
// 数据库连接
-
Connection connection = null;
-
// 预编译的Statement,使用预编译的Statement提高数据库性能
-
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 t_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) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
}
-
if (preparedStatement != null) {
-
try {
-
preparedStatement.close();
-
} catch (SQLException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
}
-
if (connection != null) {
-
try {
-
connection.close();
-
} catch (SQLException e) {
-
// TODO Auto-generated catch block
-
e.printStackTrace();
-
}
-
}
-
-
}
-
-
}
-
}
-
-
问题总结
1、数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响数据库性能。
解决方案:使用数据库连接池管理数据库连接。
2、将sql语句硬编码到java代码中,如果sql 语句修改,需要重新编译java代码,不利于系统维护。
解决方案:将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。
3、向preparedStatement中设置参数,对占位符号位置和设置参数值,硬编码在java代码中,不利于系统维护。
解决方案:将sql语句及占位符号和参数全部配置在xml中。
4、从resutSet中遍历结果集数据时,存在硬编码,将获取表的字段进行硬编码,,不利于系统维护。
解决方案:将查询的结果集,自动映射成java对象。
-
MyBatis框架原理
-
MyBatis是什么?
-
(下载地址:https://github.com/mybatis/mybatis-3/releases)
MyBatis 本是apache的一个开源项ibatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
-
原理如图
1、mybatis配置
SqlMapConfig.xml,此文件作为mybatis的全局配置文件,配置了mybatis的运行环境等信息。
mapper.xml文件即sql映射文件,文件中配置了操作数据库的sql语句。此文件需要在SqlMapConfig.xml中加载。
2、通过mybatis环境等配置信息构造SqlSessionFactory即会话工厂
3、由会话工厂创建sqlSession即会话,操作数据库需要通过sqlSession进行。
4、mybatis底层自定义了Executor执行器接口操作数据库,Executor接口有两个实现,一个是基本执行器、一个是缓存执行器。
5、Mapped Statement也是mybatis一个底层封装对象,它包装了mybatis配置信息及sql映射信息等。mapper.xml文件中一个sql对应一个Mapped Statement对象,sql的id即是Mapped statement的id。
6、Mapped Statement对sql执行输入参数进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql前将输入的java对象映射至sql中,输入参数映射就是jdbc编程中对preparedStatement设置参数。
7、Mapped Statement对sql执行输出结果进行定义,包括HashMap、基本类型、pojo,Executor通过Mapped Statement在执行sql后将输出结果映射至java对象中,输出结果映射过程相当于jdbc编程中对结果的解析处理过程。
-
入门程序
-
需求
-
对订单商品案例中的用户表进行增删改查操作
-
根据用户ID查询用户信息
-
根据用户名称模糊查询用户列表
-
添加用户
-
删除用户(练习)
-
修改用户(练习)
-
环境转呗
-
Jdk:1.8
Ide:idea
Mybatis:3.2.7
数据库:MySQL 5.7
-
数据库脚本初始化
先执行sql_table.sql再执行sql_data.sql
Sql_table
-
/*
-
SQLyog v10.2
-
MySQL - 5.1.72-community : Database - mybatis
-
*********************************************************************
-
*/
-
-
-
/*!40101 SET NAMES utf8 */;
-
-
/*!40101 SET SQL_MODE=''*/;
-
-
/*!40014 SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-
/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-
/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-
/*!40111 SET @[email protected]@SQL_NOTES, SQL_NOTES=0 */;
-
/*Table structure for table `items` */
-
-
CREATE TABLE `items` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`name` varchar(32) NOT NULL COMMENT '商品名称',
-
`price` float(10,1) NOT NULL COMMENT '商品定价',
-
`detail` text COMMENT '商品描述',
-
`pic` varchar(64) DEFAULT NULL COMMENT '商品图片',
-
`createtime` datetime NOT NULL COMMENT '生产日期',
-
PRIMARY KEY (`id`)
-
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-
-
/*Table structure for table `orderdetail` */
-
-
CREATE TABLE `orderdetail` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`orders_id` int(11) NOT NULL COMMENT '订单id',
-
`items_id` int(11) NOT NULL COMMENT '商品id',
-
`items_num` int(11) DEFAULT NULL COMMENT '商品购买数量',
-
PRIMARY KEY (`id`),
-
KEY `FK_orderdetail_1` (`orders_id`),
-
KEY `FK_orderdetail_2` (`items_id`),
-
CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
-
CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
-
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-
/* constraint 中文为约束的意思,constraint 约束名 foreign key(列名) references (主表列名)*/
-
/*Table structure for table `orders` */
-
-
CREATE TABLE `orders` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`user_id` int(11) NOT NULL COMMENT '下单用户id',
-
`number` varchar(32) NOT NULL COMMENT '订单号',
-
`createtime` datetime NOT NULL COMMENT '创建订单时间',
-
`note` varchar(100) DEFAULT NULL COMMENT '备注',
-
PRIMARY KEY (`id`),
-
KEY `FK_orders_1` (`user_id`),
-
CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
-
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
-
-
/*Table structure for table `user` */
-
-
CREATE TABLE `user` (
-
`id` int(11) NOT NULL AUTO_INCREMENT,
-
`username` varchar(32) NOT NULL COMMENT '用户名称',
-
`birthday` date DEFAULT NULL COMMENT '生日',
-
`sex` char(1) DEFAULT NULL COMMENT '性别',
-
`address` varchar(256) DEFAULT NULL COMMENT '地址',
-
PRIMARY KEY (`id`)
-
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8;
-
-
/*!40101 SET [email protected]_SQL_MODE */;
-
/*!40014 SET [email protected]_FOREIGN_KEY_CHECKS */;
-
/*!40014 SET [email protected]_UNIQUE_CHECKS */;
-
/*!40111 SET [email protected]_SQL_NOTES */;
Sql_data
-
/*
-
SQLyog v10.2
-
MySQL - 5.1.72-community : Database - mybatis
-
*********************************************************************
-
*/
-
-
-
/*!40101 SET NAMES utf8 */;
-
-
/*!40101 SET SQL_MODE=''*/;
-
-
/*!40014 SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
-
/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-
/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-
/*!40111 SET @[email protected]@SQL_NOTES, SQL_NOTES=0 */;
-
/*Data for the table `items` */
-
-
insert into `items`(`id`,`name`,`price`,`detail`,`pic`,`createtime`) values (1,'台式机',3000.0,'该电脑质量非常好!!!!',NULL,'2015-02-03 13:22:53'),(2,'笔记本',6000.0,'笔记本性能好,质量好!!!!!',NULL,'2015-02-09 13:22:57'),(3,'背包',200.0,'名牌背包,容量大质量好!!!!',NULL,'2015-02-06 13:23:02');
-
-
/*Data for the table `orderdetail` */
-
-
insert into `orderdetail`(`id`,`orders_id`,`items_id`,`items_num`) values (1,3,1,1),(2,3,2,3),(3,4,3,4),(4,4,2,3);
-
-
/*Data for the table `orders` */
-
-
insert into `orders`(`id`,`user_id`,`number`,`createtime`,`note`) values (3,1,'1000010','2015-02-04 13:22:35',NULL),(4,1,'1000011','2015-02-03 13:22:41',NULL),(5,10,'1000012','2015-02-12 16:13:23',NULL);
-
-
/*Data for the table `user` */
-
-
insert into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (1,'王五',NULL,'2',NULL),(10,'张三','2014-07-10','1','北京市'),(16,'张小明',NULL,'1','河南郑州'),(22,'陈小明',NULL,'1','河南郑州'),(24,'张三丰',NULL,'1','河南郑州'),(25,'陈小明',NULL,'1','河南郑州'),(26,'王五',NULL,NULL,NULL);
-
-
/*!40101 SET [email protected]_SQL_MODE */;
-
/*!40014 SET [email protected]_FOREIGN_KEY_CHECKS */;
-
/*!40014 SET [email protected]_UNIQUE_CHECKS */;
-
/*!40111 SET [email protected]_SQL_NOTES */;
-
搭建工程
-
Mybatis的核心包和依赖包
-
MySQl的驱动包
-
Junit(非必须)
-
代码创建
代码在Mybatis01中
-
db.properties和log4j.properties
-
创建po类
以及相应的getter和setter
-
创建全局配置文件
在config目录下,创建SqlMapConfig.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>
-
-
<!-- 加载java的配置文件或者声明属性信息 -->
-
<properties resource="db.properties">
-
</properties>
-
-
<!-- 配置mybatis的环境信息,与spring整合,该信息由spring来管理 -->
-
<environments default="development">
-
<environment id="development">
-
<!-- 配置JDBC事务控制,由mybatis进行管理 -->
-
<transactionManager type="JDBC"></transactionManager>
-
<!-- 配置数据源,采用mybatis连接池 -->
-
<dataSource type="POOLED">
-
<property name="driver" value="${db.driver}" />
-
<property name="url" value="${db.url}" />
-
<property name="username" value="${db.username}" />
-
<property name="password" value="${db.password}" />
-
</dataSource>
-
</environment>
-
</environments>
-
-
<!-- 加载映射文件 -->
-
<mappers>
-
<mapper resource="User.xml"></mapper>
-
</mappers>
-
</configuration>
-
需求加法
-
根据用户ID查询用户信息
-
映射文件
-
-
在config目录下创建user.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:命名空间,对statement的信息进行分类管理 -->
-
<!-- 注意:在mapper代理时,它具有特殊及重要的作用 -->
-
<mapper namespace="test">
-
<!-- 根据用户ID查询用户信息 -->
-
<!-- select:表示一个MappedStatement对象 -->
-
<!-- id:statement的唯一标示 -->
-
<!-- #{}:表示一个占位符? -->
-
<!-- #{id}:里面的id表示输入参数的参数名称,如果该参数是简单类型,那么#{}里面的参数名称可以任意 -->
-
<!-- parameterType:输入参数的java类型 -->
-
<!-- resultType:输出结果的所映射的java类型(单条结果所对应的java类型) -->
-
<select id="findUserById" parameterType="int" resultType="com.lichao.po.User">
-
SELECT * FROM USER WHERE id=#{id};
-
</select>
-
</mapper>
-
全局配置文件中加载映射文件
前面全局配置文件时候已经加上了
-
测试代码
在test文件夹下创建包first,新建UserTest类
-
根据用户名模糊查询用户列表
-
映射文件
-
-
测试代码
-
小结
-
#{}和${}
#{}表示占位符?,#{}接收简单类型的参数时,里面的名称可以任意
${}表示拼接符,${}接收简单类型的参数时,里面的名称必须是value
${}里面的值会原样输出,不加解析(如果该参数值是字符串,有不会添加引号)
${}存在sql注入的风险,但是有些场景下必须使用,比如排序后面会动态传入排序的列名
-
parameterType和resultType
parameterType指定输入参数的java类型,parameterType只有一个,也就是说入参只有一个。
resultType指定输出结果的java类型(是单条记录的java类型)
-
selectOne和selectList
selectOne查询单个对象
selectList查询集合对象