MyBatis基础.docx
《MyBatis基础.docx》由会员分享,可在线阅读,更多相关《MyBatis基础.docx(36页珍藏版)》请在冰点文库上搜索。
MyBatis基础
MyBatis基础
对原声jdbc程序(单独使用jdbc开发)问题总结
MyBatis入门程序
用户的增、删、改、查
MyBatis开发dao两种方法
原始dao开发(编写dao接口和dao实现类)
MyBatis的mapper(相当于dao接口)代理开发方法
MyBatis配置文件SqlMapConfig.xml
MyBatis核心
Mybatis输入映射
MyBatis输出映射
Mybatis的动态sql
订单商品数据模型分析
高级结果集映射(一对一、一对多、多对多)
MyBatis延迟加载
MyBatis查询缓存(一级缓存、二级缓存)
MyBatis和Spring整合
MyBatis逆向工程
1对原生jdbc程序中问题总结
1.1环境
Java环境:
jdk1.7
eclipse:
MySQL:
通过导入脚本,创建数据库和数据。
表结构。
测试数据,在企业开发中,最后提供一个初始化数据脚本。
1.2jdbc程序
使用jdbc查询MySQL数据库中的用户表的记录。
创建Java工程,添加数据库驱动jar包。
注意:
import导入java.sql包下的接口。
不同的数据库驱动会对这些接口有不同的实现(多态,面向接口编程)。
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
/**
*通过jdbc程序,总结其中的问题
*
*@authorZBRUI
*
*/
publicclassJdbcTest{
publicstaticvoidmain(String[]args){
//数据库连接
Connectionconnection=null;
//预编译的Statement
//使用预编译的Statement可以提高数据库的性能
PreparedStatementpreparedStatement=null;
//结果集
ResultSetresultSet=null;
try{
//加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//获取数据库连接
connection=DriverManager.getConnection(
"jdbc:
mysql:
//localhost:
3306/shop","zbrui","zbrui");
//定义sql语句,使用?
占位符
Stringsql="select*fromuserwhereusername=?
";
//获取预处理Statement
preparedStatement=connection.prepareStatement(sql);
//设置参数,占位符从1开始编号
preparedStatement.setString(1,"小红");
//想数据库发出sql执行查询,查询得到结果集
resultSet=preparedStatement.executeQuery();
//遍历结果集
while(resultSet.next()){
System.out.println(resultSet.getString("id")+","
+resultSet.getString("username"));
}
}catch(Exceptione){
e.printStackTrace();
}finally{
//释放资源
if(resultSet!
=null){
try{
resultSet.close();
}catch(Exceptione){
e.printStackTrace();
}
}
//Statement
if(preparedStatement!
=null){
try{
preparedStatement.close();
}catch(Exceptione){
e.printStackTrace();
}
}
//Connection
if(connection!
=null){
try{
connection.close();
}catch(Exceptione){
e.printStackTrace();
}
}
}
}
}
1.3问题总结
1.数据库连接,使用时创建,不适用就立即释放,对数据库进行频繁的连接开启和关闭,造成数据库资源的浪费,影响数据库性能。
解决方案:
使用数据库连接池来管理数据库连接。
2.将sql硬编码到Java代码中,如果要修改sql语句,需要重新编译Java代码,不利于系统维护。
设想:
将sql语句配置在xml配置文件中,及时sql变化,不需要对Java代码进行重新编译。
3.想preparedStatement中设置参数,对占位符号和设置参数数值,硬编码在Java代码中,不利于系统维护。
设想:
将sql语句及占位符和参数配置在xml配置文件中。
4.从resultSet结果集中遍历结果集数据时,将获取表的字段进行硬编码,不利于系统维护。
设想:
将查询结果自动映射为Java对象。
2Mybatis框架
2.1Mybatis是什么?
Mybatis是一个持久层框架,还Apache下的定级项目。
Mybatis托管到Googlecode下,后来托管到github下(http:
//)。
Mybatis让程序将主要精力放在sql上,通过mybatis提供的映射方式,自由灵活的生成(半自动化,大不分需要程序眼编写sql)满足需求的sql语句。
Mybatis可以想preparedStatement中的输入参数自动进行输入映射,将查询结果集灵活映射成Java对象(输出映射)。
2.2Mybatis框架
3入门程序
3.1需求分析和环境
需求:
根据用户id(主键)查询用户信息
根据用户名模糊查询用户信息
添加用户
删除用户
更新用户
环境:
Java:
1.7
Eclipse:
MySQL:
MyBat(jar):
3.2.7
mybatis:
核心包
cglib:
动态代理
log4j,slf4j:
日志
mysql-connection:
数据库驱动
junit,hamcrest:
Junit测试及其依赖包
3.2log4j.properties
配置日志log4j
###setloglevels-error,info,debug###
log4j.rootLogger=debug,stdout
###directlogmessagestostdout###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE}%5p%c{1}:
%L-%m%n
###directmessagestofilemylog.log###
log4j.appender.file=org.apache.log4j.FileAppender
log4j.appender.file.File=F:
/tmp/mylog.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE}%5p%c{1}:
%L-%m%n
3.3工程结构
新建sourcefolder,保存配置文件。
Sqlmap包放映射文件。
3.4SqmMapConfig.xml
配置MyBatis环境,配置数据源、事务、映射文件等。
与Spring整合之后大多数配置将省略。
约束DTD是configuration。
xmlversion="1.0"encoding="UTF-8"?
>
DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTDConfig3.0//EN"
"http:
//mybatis.org/dtd/mybatis-3-config.dtd">
--引用db.properties配置文件-->
--development:
开发模式;work:
工作模式-->
--配置数据库连接信息-->
--value属性值引用db.properties配置文件中配置的值-->
--加载映射文件-->
3.5根据用户id(主键)查询用户
根据用户id(主键)查询一条用户信息。
3.5.1创建pojo
属性名和表中字段名对应。
publicclassUser{
privateintid;
privateStringusername;
privateStringsex;
privateDatebirthday;
privateStringaddress;
//get/set
}
3.5.2映射文件
映射文件名:
User.xml(原始iBatis命名方式),mapper代理开发映射文件名叫XXXMapper.xml。
例如UserMapper.xml。
在映射文件中配置sql语句。
约束DTD是configuration。
xmlversion="1.0"encoding="UTF-8"?
>
DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN""http:
//mybatis.org/dtd/mybatis-3-mapper.dtd">
--namespace,名空间-->
--使用mapper代理方法开发,中使用-->
--在映射文件中配置sql语句-->
--通过select执行数据库查询-->
--id:
标识映射文件中的sql,statement的id将sql语句封装到mapperdStatement对象中-->
--parameterType:
指定输入参数类型-->
--resultType:
指定sql输出结果的映射的Java对象类型,select自定resultType表示将单条记录映射成的Java对象-->
--#{id}:
表示占位符,其中的id表示接收输入的参数,参数名为id。
如果输入参数是简单类型,参数名可以是value或其他名称-->
--${value}:
表示拼接sql串,将接收到的参数内容不加任何修饰拼接在sql中,可能引起sql注入。
如果传入的是简单类型,参数名只能使用value。
-->
--根据id查询用户,返回一条记录-->
resultType="com.zbrui.mybatis.po.User">
SELECT*FROMuserWHEREid=#{id}
3.5.3在SqlMapConfig.xml中加载映射文件
--加载映射文件-->
3.5.4程序代码
返回一条记录,使用selectOne()方法。
//根据id查询用户信息,得到一条记录结果
@Test
publicvoidfindUserByIdTest()throwsException{
Stringresource="SqlMapConfig.xml";
InputStreamconfig=Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder()
.build(config);
//通过工厂得到SqlSession
SqlSessionsqlSession=sqlSessionFactory.openSession();
//通过SqlSession操作数据库
//第一个参数:
映射文件中statement的id,namespace+Statement的id
//第二个参数:
parameterType类型的参数
//返回值:
resultType类型的结果
Useruser=sqlSession.selectOne("test.findUserById",1);
System.out.println(user);
//释放资源
sqlSession.close();
}
3.6根据用户名模糊查询用户信息
根据用户名模糊查询用户信息。
3.6.1映射文件
--根据用户名模糊查询,可能返回多条记录-->
resultType="com.zbrui.mybatis.po.User">
SELECT*FROMuserWHEREusernameLIKE'%${value}%'
3.6.2程序代码
返回多条,使用selectList()方法。
//根据用户名查询用户信息
@Test
publicvoidfindUserByUsernameTest()throwsException{
Stringresource="SqlMapConfig.xml";
InputStreamconfig=Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder()
.build(config);
//通过工厂得到SqlSession
SqlSessionsqlSession=sqlSessionFactory.openSession();
//通过SqlSession操作数据库
//selectList返回多条记录
Listusers=sqlSession
.selectList("test.findUserByUsername","小");
for(Useru:
users){
System.out.println(u);
}
//释放资源
sqlSession.close();
}
3.7添加用户
添加一条用户信息。
3.7.1映射文件
User.xml中配置添加用户的Statement。
--parameterType:
指定输入参数类型是pojo(包括用户信息)。
-->
--#{}:
指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值-->
--这里用户的id是自增字段,可以不写-->
insertintouser(id,username,birthday,sex,address)
value(#{id},#{username},#{birthday},#{sex},#{address})
3.7.2程序代码
通过insert添加用户,这里需要提交事务。
//根据用户名查询用户信息
@Test
publicvoidinsertUserTest()throwsException{
Stringresource="SqlMapConfig.xml";
InputStreamconfig=Resources.getResourceAsStream(resource);
//创建会话工厂
SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder()
.build(config);
//通过工厂得到SqlSession
SqlSessionsqlSession=sqlSessionFactory.openSession();
//通过SqlSession操作数据库
Useruser=newUser();
user.setUsername("张六");
user.setBirthday(newDate());
user.setSex("M");
intcou=sqlSession.insert("test.insertUser",user);
System.out.println(cou);
//提交事务
sqlSmit();
//释放资源
sqlSession.close();
}
3.7.3获取自增主键
应用场景,插入记录后,需要将主键作为其子表的外键添加到数据库中。
MySQL自增主键,执行insert提交之前自动生成一个自增主键。
通过MySQL函数获取自增主键:
LAST_INSERT_ID()
注意:
Insert之后调用这个函数。
--新增一个用户-->
--parameterType:
栈顶输入参数类型是pojo(包括用户信息)。
-->
--#{}:
指定pojo的属性名,接收到pojo对象的属性值,mybatis通过OGNL获取对象的属性值-->
--这里用户的id是自增字段,可以不写-->
--通过selectKey返回数据的主键,返回到user对象中-->
--LAST_INSERT_ID():
得到刚刚insert的记录的主键值,只使用与MySQL自增主键-->
--keyProperty:
指定返回主键值设置到parameterType的哪个属性-->
--resultType:
LAST_INSERT_ID()返回结果的类型-->
--order:
selectKey的相对于insert的执行顺序(BEFORE,AFTER)-->
selectLAST_INSERT_ID()
insertintouser(id,username,birthday,sex,address)
value(#{id},#{username},#{birthday},#{sex},#{address})
3.7.4获取非自增主键
使用MySQL的uuid()函数生成主键:
需要修改表中id字段类型为String,长度为32。
执行思路:
1.先通过uuid()查询到主键。
2.将查询到的主键设置到到parameterType对象的id中。
3.在执行insert时,从parameterType对象中取出id属性值。
注意:
执行uuid()相对于insert应当是BEFORE,即在insert之前生成主键。
通过Oracle序列生成的主键:
序列名.next()
其余类似。
3.8删除用户
根据用户id删除一条用户。
3.8.1映射文件
--根据id删除一个用户-->
updateuser
setusername=#{username},birthday=#{birthday},sex=#{sex},address=#{address}
whereid=#{id}
3.8.2程序代码
使用delete方法
需要提交事务
3.9更新用户
3.9.1映射文件
--根据id删除一个用户-->