MyBatis学习(一)---配置文件,Mapper接口和动态SQL
MyBatis
MyBatis官方学习网站
http://www.mybatis.org/mybatis-3/zh/index.html
为什么需要MyBatis?
Jdbc操作数据库的不足之处
1、需要通过硬编码的方式建立到数据库的连接
2、需要通过硬编码的方式来创建PreparedStatment对象
3、频繁的关闭连接、建立连接,导致系统的性能会下降
MyBatis
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。Mybatis框架封装了jdbc的一个持久层的框架,它和Hibernate都属于ORM框架,Hibernate是一个完全的orm框架,Mybatis不是一个完全的orm框架,不需要关注数据库连接的建立、Statement或PreparedStatement的创建,更多的去关注sql语句本身。
通过下面的项目来了解MyBatis
项目目录结构
本项目使用的Oracle数据库,项目对象的表为user_tab
src目录下是一个是MyBatis的配置文件
<?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>
<!-- 指定了默认的环境为development -->
<environments default="development">
<!-- 指出了环境的唯一标识 -->
<environment id="development">
<!-- 指出了事务管理器 -->
<transactionManager type="JDBC"/>
<!-- 指出了连接池,并指出了连接数据库的驱动,url,用户名,密码 -->
<dataSource type="POOLED">
<property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/>
<property name="username" value="scott"/>
<property name="password" value="itcast"/>
</dataSource>
</environment>
</environments>
<!-- 注册映射文件,路径中.都用/代替 -->
<mappers>
<mapper resource="com/ghq/model/dao/impl/UserDaoImpl.xml"/>
</mappers>
</configuration>
表所对应的实体类为User.java
package com.ghq.model.entity; import java.util.Date; public class User {
private int id;
private String username;
private String userpass;
private Date birthday;
private int height;
private String gender; public User(int id, String username, String userpass, Date birthday,
int height, String gender) {
this.id = id;
this.username = username;
this.userpass = userpass;
this.birthday = birthday;
this.height = height;
this.gender = gender;
}
public User(String username, String userpass, Date birthday, int height,
String gender) {
this.username = username;
this.userpass = userpass;
this.birthday = birthday;
this.height = height;
this.gender = gender;
}
public User() { }
//省略setter/getter方法
@Override
public String toString() {
return "User [id=" + id + ", username=" + username + ", userpass="
+ userpass + ", birthday=" + birthday + ", height=" + height
+ ", gender=" + gender + "]";
} }
工具类MyBatisDb.java
主要的功能是获取获取SqlSessionFactory以及SqlSession的对象,SqlSession中具有对数据表增删改查的方法。
package com.ghq.model.utils; import java.io.IOException;
import java.io.InputStream; import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MybatisDb {
private static String config = "mybatis-config.xml";
private static SqlSessionFactory sqlSessionFac; static{
try {
//读取配置文件
InputStream inputstream = Resources.getResourceAsStream(config);
//获取SqlSessionFactory对象
sqlSessionFac = new SqlSessionFactoryBuilder().build(inputstream);
} catch (IOException e) {
e.printStackTrace();
}
} //获取SqlSession对象,并且开启了事务
public static SqlSession getSession(){
return sqlSessionFac.openSession();
} }
UserDao.java 是一个接口,其中的内容主要是实现用户的增删改查功能
package com.ghq.model.dao; import java.util.List;
import com.ghq.model.entity.User; public interface UserDao {
//根据id查询用户
User getUserById(int id);
//根据模糊姓名和性别查询
List<User> getUserBynameAndGender(User u);
//新增用户
boolean addUser(User u);
//修改用户
boolean updateUser(User u);
//删除用户
boolean delUser(int id);
}
UserDaoImpl.java是UserDao的实现类
package com.ghq.model.dao.impl; import java.util.List; import org.apache.ibatis.session.SqlSession; import com.ghq.model.dao.UserDao;
import com.ghq.model.entity.User;
import com.ghq.model.utils.MybatisDb; public class UserDaoImpl implements UserDao {
//通过id获取用户的方法
@Override
public User getUserById(int id) {
//获得SQLSession对象
SqlSession session = MybatisDb.getSession();
//执行com.ghq.model.dao.impl.UserDaoImpl.getUserById标识的SQL语句,在执行前为占位参数赋值
User u = session.selectOne("com.ghq.model.dao.impl.UserDaoImpl.getUserById", id);
session.close();
return u;
} //根据模糊姓名和性别查询
@Override
public List<User> getUserBynameAndGender(User u) {
//获得SQLSession对象
SqlSession session = MybatisDb.getSession();
List<User> ulist = session.selectList("com.ghq.model.dao.impl.UserDaoImpl.getUserBynameAndGender", u);
session.close();
return ulist;
} //新增用户
@Override
public boolean addUser(User u) {
SqlSession session = MybatisDb.getSession();
int row = session.insert("com.ghq.model.dao.impl.UserDaoImpl.addUser", u);
session.commit();
session.close();
if (row > 0) {
return true;
}
return false;
} //修改用户
@Override
public boolean updateUser(User u) {
SqlSession session = MybatisDb.getSession();
int row = session.update("com.ghq.model.dao.impl.UserDaoImpl.updateUser", u);
session.commit();
session.close();
if (row > 0) {
return true;
}
return false;
} //删除用户
@Override
public boolean delUser(int id) {
SqlSession session = MybatisDb.getSession();
int row = session.delete("com.ghq.model.dao.impl.UserDaoImpl.delUser", id);
session.commit();
session.close();
if (row > 0) {
return true;
}
return false;
} }
要想实现对数据库的操作,必须配置sql的映射文件UserdaoImpl.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不允许重复,用于区分同名的SQL语句标识 -->
<mapper namespace="com.ghq.model.dao.impl.UserDaoImpl">
<!-- 映射文件中的SQL语句没有分号
#{}相当于占位符? #{}中名字标识输入参数的名字,如果输入参数是简单类型,则#{}中参数名任意
parameterType指出了输入参数类型之外的类型
resultType是结果类型,即返回的记录中单条记录的类型
-->
<select id="getUserById" parameterType="int" resultType="com.ghq.model.entity.User">
select * from user_tab where id = #{id}
</select>
<!-- 输入参数类型不是简单类型,#{}中的输入参数的名字不能任意,参数类型是自定义的实体类型,#{}中使用的是属性名,模糊查询不使用#{},而使用${} #{}两端没有单引号 -->
<select id="getUserBynameAndGender" parameterType="com.ghq.model.entity.User" resultType="com.ghq.model.entity.User">
select * from user_tab where username like '%${username}%' and gender = #{gender}
</select> <insert id="addUser" parameterType="com.ghq.model.entity.User" >
<! -- 新增用户中,用户id是通过序列来实现自动增长,所以需在数据库中创建user_tb_seq序列,然后通过select语句查询出下一个序列值,封装到标志属性中。order指出了查询是否在新增之前,是的话为BEFORE,否则为AFTER,resultType指出了查询的数据的类型,不能省略 -->
<selectKey keyProperty="id" order="BEFORE" resultType="int">
select user_tb_seq.nextval from dual
</selectKey>
insert into user_tab (id,username,userpass,birthday,height,gender) values
(#{id},#{username},#{userpass},#{birthday},#{height},#{gender})
</insert> <update id="updateUser" parameterType="com.ghq.model.entity.User">
update user_tab set username = #{username},userpass = #{userpass},birthday = #{birthday},
height = #{height},gender = #{gender} where id = #{id}
</update> <delete id="delUser" parameterType="int">
delete from user_tab where id = #{id}
</delete>
</mapper>
使用JUnit4进行单元测试testmybatis.java
package com.ghq.test; import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List; import org.junit.Test; import com.ghq.model.dao.UserDao;
import com.ghq.model.dao.impl.UserDaoImpl;
import com.ghq.model.entity.User; public class testmybatis {
@Test
public void testgetUserbyID(){
UserDao userdao = new UserDaoImpl();
User u = userdao.getUserById(7);
System.out.println(u);
} @Test
public void testgetUserbynameAndGender(){
UserDao userdao = new UserDaoImpl();
User user = new User();
user.setUsername("张");
user.setGender("女");
List<User> ulist = userdao.getUserBynameAndGender(user);
for (User uu : ulist) {
System.out.println(uu);
}
} @Test
public void testaddUser(){
UserDao userdao = new UserDaoImpl();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String str = "1990-12-12";
Date d = null;
try {
d = dateFormat.parse(str);
} catch (ParseException e) {
e.printStackTrace();
} User user = new User("张三","zs",d,160,"女");
boolean flag = userdao.addUser(user);
if (flag) {
System.out.println("插入成功");
}else{
System.out.println("插入失败");
}
} @Test
public void testupdateUser(){
UserDao userdao = new UserDaoImpl();
User user = new User(1,"李四 ","ls",new Date(),170,"男");
boolean flag = userdao.updateUser(user);
if (flag) {
System.out.println("修改成功");
}else{
System.out.println("修改失败");
}
} @Test
public void testdelUser(){
UserDao userdao = new UserDaoImpl();
boolean flag = userdao.delUser(1);
if (flag) {
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
}
}
Mapper接口
MyBatis的项目中,可以没有dao的实现类。
Mybatis 提供了 Mapper接口的代理对象,在执行 Mapper接口方法时,实际执行的是Mybatis的代理对象,代理对象在 invoke 方法内获取 Mapper接口类全名+方法全名 作为statement的ID,然后通过ID去Statement匹配注册的SQL,然后使用 SqlSession 执行这个 SQL。
实现这样的功能前提是映射文件和接口主文件名相同,且在同一个包下,映射文件的命名空间是接口的全限定名。
在mybatis-config.xml配置文件中
1、注册映射文件时,若映射文件过多,推荐使用批量注册映射文件。
批量注册映射文件的前提是:接口的主文件名要和相应映射文件名一致,而且映射文件中的namespace是接口的全限定名,接口和映射文件在同一个包下
<!-- 注册映射文件(批量注册映射文件,注册com.ghq.model.dao下的所有配置文件) -->
<mappers>
<package name="com.ghq.model.dao"/>
</mappers>
2、在配置文件中定义别名,可以在映射文件中使用别名。
<!-- 在配置文件中定义别名,可以在映射文件中使用别名 -->
<typeAliases>
<!-- 一次定义一个别名 -->
<!-- <typeAlias type="com.ghq.model.entity.User" alias="user"/> -->
<!-- 为该包下的实体类定义别名 -->
<package name="com.ghq.model.entity"/>
</typeAliases>
定义别名后,可以在resultType或paramterType中使用user
3、可以将连接数据库的驱动,url,用户名和密码存放在properties文件中。
db.properties文件中的配置
db.driver=oracle.jdbc.driver.OracleDriver
db.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
db.username=scott
db.password=itcast
<!-- 加载db.properties文件 -->
<properties resource="db.properties"></properties> <environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<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>
以根据id查询用户为例:
UserDao中的代码
public interface UserDao {
//根据id查询用户
User getUserById(int id);
}
UserDao的映射文件UserDao.xml
<mapper namespace="com.ghq.model.dao.UserDao">
<select id="getUserById" parameterType="int" resultType="user">
select * from user_tab where id = #{id}
</select>
</mapper>
单元测试的代码
public class testmybatis {
@Test
public void testgetUserbyID(){
SqlSession session = MybatisDb.getSession();
UserDao userdao = session.getMapper(UserDao.class);
User u = userdao.getUserById(1);
System.out.println(u);
}
}
动态sql语句
动态sql语句涉及的元素
1、where
where元素默认去除第一个and,如果参数输入不合法,则会删掉where子句
2、if
对输入参数进行条件判断,if标签中test属性中的不存在&&,使用and代替
3、foreach
用于产生一个集合
工具类Uservo.java
package com.ghq.model.entity; import java.util.List; public class UserVo {
private List<Integer> idlist; public List<Integer> getIdlist() {
return idlist;
} public void setIdlist(List<Integer> idlist) {
this.idlist = idlist;
}
}
UserDao.java
//根据模糊姓名和性别查询
List<User> getUserBynameAndGender(Map<String,Object> m);
//查询一个主键范围的用户列表
public List<User> getUsersWithIdList(UserVo vo);
UserDao.xml
<select id="getUserBynameAndGender" parameterType="java.util.Map" resultType="user">
select * from user_tab
<!-- where 标签默认会去除第一个and,若输入参数是null,则删除where条件 -->
<where>
<if test="username != null and username != ''">
and username like '%${username}%'
</if>
<if test="gender !=null and gender !=''">
and gender = #{gender}
</if>
</where>
</select> <select id="getUsersWithIdList" parameterType="UserVo" resultType="user">
select * from user_tab
<where>
<if test="idlist !=null">
and id in
<foreach collection="idlist" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
单元测试
public class testmybatis {
@Test
public void testgetUserbynameAndGender(){
SqlSession session = MybatisDb.getSession();
UserDao userdao = session.getMapper(UserDao.class);
Map<String,Object> user = new HashMap<String,Object>();
user.put("username", "张");
user.put("gender", "女");
List<User> ulist = userdao.getUserBynameAndGender(user);
for (User uu : ulist) {
System.out.println(uu);
} } //批量查询id为1,2,3的用户
@Test
public void testgetUsersWithIdList(){
SqlSession session = MybatisDb.getSession();
UserDao userdao = session.getMapper(UserDao.class); UserVo vo = new UserVo();
List<Integer> idlist = new ArrayList<Integer>();
idlist.add(1);
idlist.add(2);
idlist.add(3);
vo.setIdlist(idlist);
List<User> list = userdao.getUsersWithIdList(vo);
for (User user : list) {
System.out.println(user);
}
}
}
select元素中resultMap属性
用于解决查询数据表时,查询出的列名和实体的属性名不一致,该属性值要和
resultMap元素的id一致,该resultMap元素就来完成查询出的列名和实体的属性名的映射,如果查询出的列名和实体的属性名一致,select元素使用resultType就可以,不需要使用resultMap属性。
MyBatis学习(一)---配置文件,Mapper接口和动态SQL的更多相关文章
- Mybatis学习笔记(四) 之动态SQL语句
动态SQL mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类: 1. if 语句 (简单的条件 ...
- Mybatis学习笔记(五) —— Mapper.xml(输入映射和输出映射)
一.parameterType(输入类型) 1.1 传递简单类型 <!-- 根据用户id查询用户 --> <select id="queryUserById" p ...
- Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring
Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring 非原创[只为记录],原博文地址:https://www.cnblogs.com/ ...
- (转)Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring
Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring Mybatis在与Spring集成的时候可以配置MapperFactoryBea ...
- Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客 - 推酷 - 360安全浏览器 7.1
Mybatis MapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring - 大新博客 时间 2014-02-11 21:08:00 博客园-所有随笔区 ...
- MyBatis基础入门《二十》动态SQL(foreach)
MyBatis基础入门<二十>动态SQL(foreach) 1. 迭代一个集合,通常用于in条件 2. 属性 > item > index > collection : ...
- MyBatis基础入门《十八》动态SQL(if-where)
MyBatis基础入门<十八>动态SQL(if-where) 描述: 代码是在<MyBatis基础入门<十七>动态SQL>基础上进行改造的,不再贴所有代码,仅贴改动 ...
- MyBatis基础入门《十九》动态SQL(set,trim)
MyBatis基础入门<十九>动态SQL(set,trim) 描述: 1. 问题 : 更新用户表数据时,若某个参数为null时,会导致更新错误 2. 分析: 正确结果: 若某个参数为nul ...
- 加载映射文件几种方式和mapper接口注解执行sql语句
一.加载映射文件几种方式 二.mapper接口注解执行sql语句 就将xml中的sql语句放到注解的括号中就可以,一般只用于简单的sql语句合适:
随机推荐
- AngularJS源码解析1:angular自启动过程
angularJS加载进来后,会有一个立即执行函数调用,在源代码的最下面是angular初始化的地方.代码展示: bindJQuery(); publishExternalAPI(angular); ...
- mybatis常用默认配置
设置参数 描述 有效值 默认值 cacheEnable 该配置影响所有映射器中配置的缓存全局开关 true.false true lazyLoadingEnable 延迟加载的全局开关.当它开启时,所 ...
- Lambda入门
Lambda 来源于微积分数学中的 λ,其涵义是声明为了表达一个函数具体需要什么. Table of contents Introduction 使用 Introduction 什么是Lambda? ...
- C# ListView用法详解 很完整
一.ListView类 1.常用的基本属性: (1)FullRowSelect:设置是否行选择模式.(默认为false) 提示:只有在Details视图该属性才有意义. (2) GridLines:设 ...
- [转] Java中Comparator进行对象排序
[From] https://blog.51cto.com/thinklili/2063244 Java在8后引入了lambda表达式和流,使得排序方法有了变化 class User { int id ...
- 用Docker构建分布式Redis集群
[编者的话]本文介绍了如何使用Docker搭建Redis集群,很多读者都在问Docker能带来哪些实质性的好处,我想本文就是一个很好的例子.不使用Docker你也可以搭建Redis集群,那使用Dock ...
- 利用js对象的特性,去掉数组中的重复项
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/stri ...
- 深度学习(七)U-Net原理以及keras代码实现医学图像眼球血管分割
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9780786.html DRIVE数据集下载百度云链接:链接:https://pan.baidu ...
- JavaScript设计模式-19.代理模式
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 有线mac 无线MAC 地址&&telnet要先开服务: ipconfig /all getma
在向IEEE申请到Mac address后,写到Lan设备里,就是Lan Mac,写到Wlan设备里,就是wlan Mac,写到BT设备里,就是BT Mac. MAC(Media Access Con ...