Java框架之Mybatis(一)
一、Mybatis 简介
Mybatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为Mybatis , 2013年11月迁移到Github , iBATIS一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)Mybatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架。Mybatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。Mybatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
二、Mybatis 的执行框架
1) SqlMapConfig.xml 文件 //名称不一定是这个名称 类似hibernate中的主配置文件
主配置文件 配置数据源,事务等运行环境,配置映射文件 (xxXmapper.xml... 多个)
2) SessionFactory
会话工厂,它是根据配置文件创建的,用来创建 SqlSession
3) SqlSession
会话 ,是一个接口,面向用户的接口,主要用来进行数据库操作
4) Executor
执行器,是底层封装的一个对象,是一个接口(底层有两个实现,基本执行器,缓存执行器)事实上 SqlSession 的内部就是通过该接口来执行sql语句的
5) MappedStatement 底层封装的对象,封装sql ,输入参数,输出结果类型等
三、第一个hello world 程序
1) 导包
asm-3.3.1.jar
cglib-2.2.2.jar
commons-logging-1.1.1.jar
javassist-3.17.1-GA.jar
log4j-1.2.17.jar
log4j-api-2.0-rc1.jar
log4j-core-2.0-rc1.jar
Mybatis-3.2.6.jar
slf4j-api-1.7.5.jar
slf4j-log4j12-1.7.5.jar
2) 在config里建一个配置文件(数据库相关的) mydbconfig.properties , 内容如下
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost:3306/shop
db.username=admin
db.password=root
3) 建立 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>
<properties resource="mydbconfig.properties" /> <environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED"> //POOLED指的是org.apache.ibatis.datasource.pooled.PooledDataSource, 一个数据源的实现类
<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="sqlmap/UserInfo.xml" />
</mappers>
</configuration>
4) 编写映射文件 (其实就是bean 对应的映射文件 相当于 hibernate 中的 UsesrInfo.hbm.xml 之类的 )
命名规则 :
== UserInfo.xml //过去的ibatis中
== 如果使用了mapper 代理 命名规则变为 UserInfoMapper.xml
//UserInfo.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"> <mapper namespace="test">
<select id="getuser_byid" parameterType="int" resultType="cat.beans.UserInfo" >
select * from userInfo where id=#{id} //如是简单类型,id可以写成任意名字
</select>
</mapper>
说明: namespace 是命名空间,用来对sql进行隔离 ,注意,如果使用mapper代理的方式开发,它就有特殊的作用
-- <select id="getuser_byid" ... > 这个id 就是sql的标识,其实将来要封装到 MappedStatement 中
-- #{ } 代表占位
-- 如是参数是简单类型,{} 中的名字可以任意
-- resultType 表示返回的java对象的类型,表示要将查询结果映射成什么样的java对象
5) 在主配置文件中引入这个映射文件
主配置文件中加入
<mappers>
<mapper resource="sqlmap/UserInfo.xml" />
</mappers>
//上面的主配置文件中其实已经加入了
6)测试
static void test(){
//加载主配置文件
InputStream in=Test.class.getClassLoader().getResourceAsStream("SqlMapConfig.xml");
//InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml"); //Resources是mhybatis 提供的
SqlSessionFactory factor=new SqlSessionFactoryBuilder().build(in);
SqlSession session =factor.openSession();
//第一个参数,是sql的id (是映射文件中的statement的id) = 名称空间+sql的id名称 ,
UserInfo user=session.selectOne("test.getuser_byid",1); //注意,这里的1 不能定成 "1"
System.out.println(user);
session.close();
}
在上例的基础上,再添一个模糊查询的例子
在 UserInfo.xml 中 加入
<select id="getuser_biname" parameterType="string" resultType="cat.beans.UserInfo">
//select * from userInfo where userName like #{value} //不行, 它会拼成like '张三'
select * from userInfo where userName like '%${value}%' // ${value} 表示会把传过来的值,直接拼到串上,有可能有sql注入问题,而且
// 如果parameterType 是简单类型,则${ } 中间的必须写成 value
</select>
static void test() throws IOException{
InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factor=new SqlSessionFactoryBuilder().build(in);
SqlSession session =factor.openSession();
UserInfo user=session.selectOne("test.getuser_byid",1); //注意,这里的1 不能定成 "1"
System.out.println(user);
session.close();
}
总结:
#{} Mybatis 将 #{} 解释为jdbc PreparedStatement 的一个参数标记 // 就是 select * from t where id= ? 中的 ?
${} 将它直接解释为字符串
理解这两者的区别是很有用的, 因为在某些SQL语句中并不能使用参数标记(parameter markers)。
那如果有like查询要怎么办呢? 可以这样sql写成第一种 #{} ,传参的时候如下
"%张三%"
selectOne //返回一个对象
selectList //返回一组对象 两者 resultType="cat.beans.UserInfo" 都正常
在上例的基础上,再增加一个添加用户的功能
//对于添加这类方法,是没有resultType的
<insert id="add_user" parameterType="cat.beans.UserInfo" >
insert into userInfo (userName,password,note) values (#{userName},#{password}, #{note} ) //后面不要写上分号
</insert>
tatic void test3() throws IOException{ InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factor=new SqlSessionFactoryBuilder().build(in);
SqlSession session =factor.openSession(); UserInfo user=new UserInfo();
user.setUserName("陈鹏飞");
user.setPassword("admin");
user.setNote("这是备注"); int result=session.insert("test.add_user",user); // 对于inser,虽然没有为sql声明反回类型,但也能正确的取到反回值的,它是整型 session.commit(); //不要忘了提交事务
System.out.println(result); //能得到正确的值 1 session.close();
}
在上面的基础上,再添加删除的和修改的功能
<delete id="deluser_byid" parameterType="int" >
delete from userInfo where id=#{id}
</delete> <update id="update_user" parameterType="cat.beans.UserInfo" > <!-- 传过来的userInfo对象中要有id -->
update userInfo set userName= #{userName},password= #{password}, note =#{note} where id= #{id}
</update>
//修改
static void test4() throws IOException{ InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factor=new SqlSessionFactoryBuilder().build(in);
SqlSession session =factor.openSession(); UserInfo user=session.selectOne("test.getuser_byid",1);
user.setUserName("english");
user.setPassword("englishxxx");
user.setNote("englishxxx");
int result= session.update("test.update_user",user);
session.commit();
System.out.println("修改成功: " + result); session.close();
} //删除
static void test5() throws IOException{
InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factor=new SqlSessionFactoryBuilder().build(in);
SqlSession session =factor.openSession();
int result= session.delete("test.deluser_byid",10);
session.commit();
System.out.println("删除成功: " + result);
session.close();
}
四、返回自增主键
mysql 有一个函数 last_insert_id() 可以调用它得到最后一条插入语句生成的自增主键。
在上面的用户添加的例子上
<insert id="add_user" parameterType="cat.beans.UserInfo" >
<selectKey order="AFTER" keyProperty="id" resultType="int"> //resultType 必填 keyProperty的id 就是userInfo.id
select last_insert_id()
//elect new uuid(); //这是mysql生成uui的写法 (32位数字或字母,4位是 -) 如果这样,上面的AFTER要改成before
//select 序列名.nextval 这是oracle中的写法
</selectKey>
insert into userInfo (userName,password,note) values (#{userName},#{password}, #{note} )
</insert>
说明:
order="AFTER" 指的是 要在这条语句执行之后取得生成的主键,它还有另一个取值 BEFORE
非自增主键,想取得,要用BEFORE,但生成主键的方式应该是上面的红色的注起来的方式。
注意,如果用的是后面的方式,则下面的sql要写上id
例子:生成 uuid型的主键
<insert id="add_user_new" parameterType="cat.beans.UserInfo" >
<selectKey order="BEFORE" keyProperty="id" resultType="string"> //注意返回类型,注意前面要写成 BEFORE
select uuid()
</selectKey>
insert into userInfo (id,userName,password,note) values (#{id},#{userName},#{password}, #{note} )
//注意要把id这列也写上
</insert> UserInfo user=new UserInfo();
//user.setId() 不用写了,因为主键由Mybatis生成 user.setUserName("郑某某");
user.setPassword("admin");
user.setNote("这是备注"); session.insert("test.add_user_new",user);
session.commit(); System.out.println(user.getId()); //可以取到主键 369010c6-e631-1033-b927-e281dfdaa6b0
五、dao层的开发
SessionFactory 可以做成单例 (未来会交给Spring管理)
SqlSession 是线程不安全的, 用的时候,要在方法体内 , 这样它就是一个局部变量,千万不要把它写成类成员
Mybatis 开发DAO 有两种方式
原始的方式 ,手写dao 和实现类
//接口 :
public interface IUserDao {
int addUser(UserInfo user);
UserInfo getUserById(int id);
} //实现类
public class UserDaoImplTest {
private IUserDao _dao ;
@Before
public void setUp() throws Exception {
InputStream in= Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factor=new SqlSessionFactoryBuilder().build(in);
_dao=new UserDaoImpl(factor);
} @Test
public void testAddUser() {
UserInfo user=new UserInfo();
user.setUserName("周周");
user.setPassword("admin"); int result=_dao.addUser(user);
System.out.println("ok"+result);
} @Test
public void testGetUserById() {
UserInfo user=_dao.getUserById(2);
System.out.println(user);
} }
测试用例
使用 mapper 代理的方式 ,只需要mapper接口 (相当于dao接口)
public class UserDaoImpl implements IUserDao {
private SqlSessionFactory _factory;
public UserDaoImpl(SqlSessionFactory factory){
this._factory=factory; //由外界注入 SqlSessionFactory
}
//添加用户
public int addUser(UserInfo user) {
SqlSession s =_factory.openSession();
int result=s.insert("test.add_user",user);
s.commit();
return result;
}
//查询用户
public UserInfo getUserById(int id) {
SqlSession s =_factory.openSession();
UserInfo user=s.selectOne("test.getuser_byid",id);
s.commit();
return user;
}
}
配置文件
<mapper namespace="test">
<select id="getuser_byid" parameterType="int" resultType="cat.beans.UserInfo" >
select * from userInfo where id=#{id}
</select> <insert id="add_user" parameterType="cat.beans.UserInfo" >
<selectKey order="AFTER" keyProperty="id" resultType="int">
select last_insert_id()
</selectKey>
insert into userInfo (userName,password,note) values (#{userName},#{password}, #{note} )
</insert> ... 其他的略 </mapper>
Java框架之Mybatis(一)的更多相关文章
- Java框架篇---Mybatis 入门
一.Mybatis介绍 MyBatis是一款一流的支持自定义SQL.存储过程和高级映射的持久化框架.MyBatis几乎消除了所有的JDBC代码,也基本不需要手工去设置参数和获取检索结果.MyBatis ...
- Java框架之Mybatis(二)
本文主要介绍 Mybatis(一)之后剩下的内容: 1 mybatis 中 log4j的配置 2 dao层的开发(使用mapper代理的方式) 3 mybatis的配置详解 4 输入输出映射对应的类型 ...
- java框架之mybatis
一.简介 1.基本概念 mybatis 是一个半自动轻量级的一个 orm 框架 将 java 与 sql 分离,解决了 jdbc 的硬编码问题: sql 由开发人员控制,更加方便 sql 的修改调优: ...
- java框架之MyBatis(1)-入门&动态代理开发
前言 学MyBatis的原因 1.目前最主流的持久层框架为 Hibernate 与 MyBatis,而且国内公司目前使用 Mybatis 的要比 Hibernate 要多. 2.Hibernate 学 ...
- Java框架之MyBatis框架(二)
Mybatis框架是相对于优化dao层的框架,其有效的减少了频繁的连接数据库(在配置文件xml中进行配置),将sql语句与java代码进行分离(写在XXXXmapper.xml文件中,一个表对应一个x ...
- Java框架之MyBatis框架(一)
一.框架介绍: MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动.创建connection.创建sta ...
- Java框架之MyBatis 06-全局配置-mapper映射-分步查询
MyBatis MyBatis是Apache的一个开源项目iBatis, iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架. iBatis 提供的持 ...
- Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件
MyBatis 今天大年初一,你在学习!不学习做什么,斗地主...人都凑不齐.学习吧,学习使我快乐!除了诗和远方还有责任,我也想担当,我也想负责,可臣妾做不到啊,怎么办?你说怎么办,为啥人家能做到你做 ...
- Java框架篇---Mybatis 构建SqlSessionFactory
从 XML 中构建 SqlSessionFactory 基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为中心的.SqlSessionFactory 的实例可以通过 ...
随机推荐
- python用户管理系统
学Python这么久了,第一次写一个这么多的代码(我承认只有300多行,重复的代码挺多的,我承认我确实垃圾),但是也挺不容易的 自定义函数+装饰器,每一个模块写的一个函数 很多地方能用装饰器(逻辑跟不 ...
- Java爬虫_资源网站爬取实战
对 http://bestcbooks.com/ 这个网站的书籍进行爬取 (爬取资源分享在结尾) 下面是通过一个URL获得其对应网页源码的方法 传入一个 url 返回其源码 (获得源码后,对源码进 ...
- 关于hash和ico的一些关联
最近測试提出一个bug.说某几个页面中的ico不显示,于是针对此问题排查原因. 首先,确保页面中的link已引入favicon.ico. 经查看,发现是js中的location.hash导致了ico不 ...
- 最全面的JS表单验证
两个日期比較 /* 用途:检查開始日期是否小于等于结束日期 输入: s:字符串 開始日期 格式:2001-5-4 e:字符串 结束日期 格式:2002-5-4 返回: 假设通过開始日期小于等于结 ...
- 【Notification】屏蔽特定应用的通知提示
须要默认屏蔽特定app的通知提示 设置app是否接收通知的界面 点击每一个条目进去的界面 AppNotificationSettings extends SettingsPreferenceFragm ...
- Zend_Json 简介 --(手冊)
1. 简单介绍 Zend_Json 提供一个方便的方式来串联(native的)PHP(的变量)和JSON,并将JSON(对象)解码到PHP中. 2. 基本使用方法 Zend_Json的使用包含使用 ...
- 单行json_ajax
html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...
- 深入理解计算机系统_3e 第五章家庭作业 CS:APP3e chapter 5 homework
5.13 A. B. 由浮点数加法的延迟,CPE的下界应该是3. C. 由整数加法的延迟,CPE的下界应该是1. D. 由A中的数据流图,虽然浮点数乘法需要5个周期,但是它没有"数据依赖&q ...
- django+Echarts实现数据可视化
1.实时异步加载(从mysql读取数据) 2.scatter散点图 3.雷达图(参数选择要注意) time_1 time_2 time_3 4.面积图 我上传的源码请到github下载:https:/ ...
- 《软件测试的艺术(原书第2版)》【PDF】下载
<软件测试的艺术(原书第2版)>[PDF]下载链接: https://u253469.ctfile.com/fs/253469-231196343 内容简介 本书以一次自评价测试开篇,从软 ...