1、数据库连接频繁的创建和关闭,缺点浪费数据库的资源,影响操作效率
设想:使用数据库连接池
2、sql语句是硬编码,如果需求变更需要修改sql,就需要修改java代码,需要重新编译,系统不易维护。
设想:将sql语句统一配置在文件中,修改sql不需要修改java代码。
3、通过preparedStatement向占位符设置参数,存在硬编码( 参数位置,参数)问题。系统不易维护。
设想:将sql中的占位符及对应的参数类型配置在配置文件中,能够自动输入映射。
4、遍历查询结果集存在硬编码(列名)。
设想:自动进行sql查询结果向java对象的映射(输出映射)。
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis,实质上Mybatis对ibatis进行一些改进。 目前mybatis在github上托管。
MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动、创建connection、创建statement、手动设置参数、结果集检索等jdbc繁杂的过程代码。
Mybatis通过xml或注解的方式将要执行的各种statement(statement、preparedStatemnt、CallableStatement)配置起来,并通过java对象和statement中的sql进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射成java对象并返回。
jdk1.6.0_45
myeclips10.0
mysql:mysql5.1
从mybatis管网下载(地址:https://github.com/mybatis/mybatis-3/releases)
mybatis-3.2.7.pdf---操作手册
mybatis-3.2.7.jar--核心 jar包
依赖的jar包
需要数据库的驱动包:
Mysql-connector-java-5.1.7-bin
数据库中有已经导入的四个表:items:(商品信息表);orderdetail:(订单明细表);orders:(订单表);user:(用户表)
1 CREATE TABLE items ( 2 id INT NOT NULL AUTO_INCREMENT, 3 itemsname VARCHAR(32) NOT NULL COMMENT '商品名称', 4 price FLOAT(10,1) NOT NULL COMMENT '商品定价', 5 detail TEXT COMMENT '商品描述', 6 pic VARCHAR(64) DEFAULT NULL COMMENT '商品图片', 7 createtime DATETIME NOT NULL COMMENT '生产日期', 8 PRIMARY KEY (id) 9 ) DEFAULT CHARSET=utf8; 10 11 /*Table structure for table `orderdetail` */ 12 13 CREATE TABLE orderdetail ( 14 id INT NOT NULL AUTO_INCREMENT, 15 orders_id INT NOT NULL COMMENT '订单id', 16 items_id INT NOT NULL COMMENT '商品id', 17 items_num INT DEFAULT NULL COMMENT '商品购买数量', 18 PRIMARY KEY (id), 19 KEY `FK_orderdetail_1` (`orders_id`), 20 KEY `FK_orderdetail_2` (`items_id`), 21 CONSTRAINT `FK_orderdetail_1` FOREIGN KEY (`orders_id`) REFERENCES `orders` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, 22 CONSTRAINT `FK_orderdetail_2` FOREIGN KEY (`items_id`) REFERENCES `items` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 23 ) DEFAULT CHARSET=utf8; 24 25 /*Table structure for table `orders` */ 26 27 CREATE TABLE orders ( 28 id INT NOT NULL AUTO_INCREMENT, 29 user_id INT NOT NULL COMMENT '下单用户id', 30 number VARCHAR(30) NOT NULL COMMENT '订单号', 31 createtime DATETIME NOT NULL COMMENT '创建订单时间', 32 note VARCHAR(100) DEFAULT NULL COMMENT '备注', 33 PRIMARY KEY (`id`), 34 KEY `FK_orders_1` (`user_id`), 35 CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 36 ) DEFAULT CHARSET=utf8; 37 38 /*Table structure for table `t_user` */ 39 40 CREATE TABLE user ( 41 id INT NOT NULL AUTO_INCREMENT, 42 username VARCHAR(32) NOT NULL COMMENT '用户名称', 43 birthday DATE DEFAULT NULL COMMENT '生日', 44 sex CHAR(1) DEFAULT NULL COMMENT '性别', 45 address VARCHAR(256) DEFAULT NULL COMMENT '地址', 46 PRIMARY KEY (`id`) 47 ) DEFAULT CHARSET=utf8;
1 /*Data for the table `items` */ 2 3 INSERT INTO items(itemsname,price,detail,pic,createtime) VALUES 4 ('台式机',3000.0,'该电脑质量非常好!',NULL,'2015-07-07 13:28:53'), 5 ('笔记本',6000.0,'笔记本性能好,质量好!',NULL,'2015-07-08 13:22:57'), 6 ('背包',200.0,'名牌背包,容量大质量好!',NULL,'2015-07-010 13:25:02'); 7 8 /*Data for the table `orderdetail` */ 9 10 INSERT INTO `orderdetail`(`orders_id`,`items_id`,`items_num`) VALUES 11 (1,1,1), 12 (1,2,3), 13 (2,3,4), 14 (3,2,3); 15 16 /*Data for the table `orders` */ 17 18 INSERT INTO `orders`(`user_id`,`number`,`createtime`,`note`) VALUES 19 (1,'1000010','2015-06-04 13:22:35',NULL), 20 (1,'1000011','2015-07-08 13:22:41',NULL), 21 (2,'1000012','2015-07-17 14:13:23',NULL), 22 (3,'1000012','2015-07-16 18:13:23',NULL), 23 (4,'1000012','2015-07-15 19:13:23',NULL), 24 (5,'1000012','2015-07-14 17:13:23',NULL), 25 (6,'1000012','2015-07-13 16:13:23',NULL); 26 27 /*Data for the table `user` */ 28 29 INSERT INTO `user`(`username`,`birthday`,`sex`,`address`) VALUES 30 ('王五',NULL,'2',NULL), 31 ('张三','2014-07-10','1','北京市'), 32 ('张小明',NULL,'1','河南郑州'), 33 ('陈小明',NULL,'1','河南郑州'), 34 ('张三丰',NULL,'1','河南郑州'), 35 ('陈小明',NULL,'1','河南郑州'), 36 ('王五',NULL,NULL,NULL), 37 ('小A','2015-06-27','2','北京'), 38 ('小B','2015-06-27','2','北京'), 39 ('小C','2015-06-27','1','北京'), 40 ('小D','2015-06-27','2','北京');
实现用户查询:
根据用户id(主键)查询用户信息(单条记录)
#Global logging configuration,建议开发环境中要用debug
log4j.rootLogger=DEBUG, stdout
#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
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=root
通过SqlMapConfig.xml加载mybatis运行环境。
<!DOCTYPEconfiguration
PUBLIC "-//mybatis.org//DTDConfig 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 属性定义
加载一个properties文件db.properties是和数据库连接的一些信息
在 properties标签中配置属性值
-->
<propertiesresource="db.properties">
</properties>
<!-- 和spring整合后 environments配置将废除-->
<environmentsdefault="development">
<environmentid="development">
<!-- 使用jdbc事务管理-->
<transactionManagertype="JDBC"/>
<!-- 数据库连接池-->
<dataSourcetype="POOLED">
<propertyname="driver"value="${jdbc.driver}"/>
<propertyname="url"value="${jdbc.url}"/>
<propertyname="username"value="${jdbc.username}"/>
<propertyname="password"value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<!-- 通过resource引用mapper的映射文件 -->
<mapperresource="sqlmap/User.xml"/>
</mappers>
</configuration>
建议命名规则:表名+mapper.xml
早期ibatis命名规则:表名.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEmapper
PUBLIC "-//mybatis.org//DTDMapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace命名空间,为了对sql语句进行隔离,方便管理,mapper开发dao方式,使用namespace有特殊作用
mapper代理开发时将namespace指定为mapper接口的全限定名
-->
<mappernamespace="firstDemo">
<!--在mapper.xml文件中配置很多的sql语句,执行每个sql语句时,封装为MappedStatement对象
mapper.xml以statement为单位管理sql语句
-->
<!-- 根据id查询用户信息 -->
<!--
id:唯一标识一个statement
#{}:表示一个占位符,如果#{}中传入简单类型的参数,#{}中的名称随意
parameterType:输入参数的类型,通过#{}接收parameterType输入的参数
resultType:输出结果类型,不管返回是多条还是单条,指定单条记录映射的pojo类型
-->
<selectid="findUserById"parameterType="int"resultType="cn.itcast.mybatis.po.User">
SELECT * FROM USER WHERE id= #{id}
</select>
</mapper>
package com.itcast.test; import java.io.IOException; import java.io.InputStream; import org.apache.ibatis.io.Resources; importorg.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; importorg.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.Before; import org.junit.Test; import cn.itcast.mybatis.po.User; public class FirstTest { //定义一个会话工厂 privateSqlSessionFactory sqlSessionFactory; @Before publicvoid init() throws IOException { //加载配置文件 Stringresource = "sqlMapConfig.xml"; //加载文件到输入流 InputStreaminputStream = Resources.getResourceAsStream(resource); //创建回话工厂 sqlSessionFactory= new SqlSessionFactoryBuilder().build(inputStream); } /* * 测试根据Id查询用户获取单条记录 */ @Test publicvoid testFindUserById(){ //通过sqlSessionFactory创建sqlSession SqlSessionsqlSession = sqlSessionFactory.openSession(); //通过sqlSession操作数据库 //第一个参数:statment的位置,等于namespace+statment的id //第二个参数:传入的参数 User user = null; try{ user= sqlSession.selectOne("firstDemo.findUserById", 26); }catch (Exception e) { e.printStackTrace(); }finally{ //关闭sqlSession //这里放在try/catch语句的finally确保查询之后能关闭sqlSession sqlSession.close(); } System.out.println(user); } }<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"> </span>
1、 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。
2、 Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
3、 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
4、 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。