JavaEE框架——Mybatis入门和和使用(增删改查,缓存)
Posted wangjian_an
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaEE框架——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 的前身就是 iBatis,iBatis 本是由 ClintonBegin 开发,后来捐给 A pache 基金会,成立了 iBatis 开源项目 。 2010 年 5 月该项目由 A pahce 基金会迁移到了 G oogle C ode, 并且改名为 M y B atis 。尽管如此,它的包结构仍然为 ibatis 。
-
访问网站
www.mybatis.org/ https://github.com/mybatis - MyBatis 是一个数据持久层 ( ORM ) 框架。 把实体类和 SQL 语句之间建立了映射关系,是一种半自动化的 ORM 实现。
- 所有 sql 语句,全部定义在 xml (建议)中。也可以通过注解的方式在接口上实现。这些映射文件称之为 mapper 。
二、MyBatis的优点(与其他架构区别)
- MyBatis的优点:
- 基于SQL语法,简单易学。
- 能了解底层组装过程。
- SQL语句封装在配置文件中,便于统一管理与维护,降低了程序的耦合度。
- 程序调试方便。
- 与传统JDBC的比较
- 减少了 61% 的代码量
- 最简单的持久化框架
- 架构级性能增强
- SQL 代码从程序代码中彻底分离,可重用
- 增强了项目中的分工
- 增强了移植性
- 与Hibernate的对比
-
MyBatis和Hibernate比较 MyBatis Hibernate
是一个SQL语句映射的框架(工具) 主流的ORM框架、提供了从POJO到数据库表的全套映射机制 注重POJO/Map与SQL之间的映射关系。不会为程序员在运行期自动生成SQL 会自动生成全套SQL语句。 自动化程度低、手工映射SQL,灵活程度高 因为自动化程度高、映射配置复杂,api也相对复杂,灵活性低. 需要开发人员熟炼掌据SQL语句 开发人同不必关注SQL底层语句开发
三、架构
1.功能架构讲解:
我们把Mybatis的功能架构分为三层:- API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
- 数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
- 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。
2.框架架构讲解:
- 加载配置:配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信息加载成为一个 mybatis结构 个MappedStatement对象(包括了传入参数映射配置、执行的SQL语句、结果映射配置),存储在内存中。
- SQL解析:当API接口层接收到调用请求时,会接收到传入SQL的ID和传入对象(可以是Map、JavaBean或者基本数据类型),Mybatis会根据SQL的ID找到对应的MappedStatement,然后根据传入参数对象对MappedStatement进行解析,解析后可以得到最终要执行的SQL语句和参数。
- SQL执行:将最终得到的SQL和参数拿到数据库进行执行,得到操作数据库的结果。
- 结果映射:将操作数据库的结果按照映射的配置进行转换,可以转换成HashMap、JavaBean或者基本数据类型,并将最终结果返回。
四、MyBatis基本要素
somename.xml全局配置文件 mapper.xml核心映射文件 SqlSession接口1.基础配置文件mybatis-config.xml
-
configuration.xml是系统的核心配置文件,包含数据源和事务管理器等设置和属性信息,XML文档结构如下:
configuration 配置 properties 可以配置在 Java 属性配置文件中 settings 修改 MyBatis 在运行时的行为方式,如是否需要缓存 typeAliases 为 Java 类型命名一个短的名字 typeHandlers 类型处理器-系统默认已经为所有类型设置 OK objectFactory 对象工厂 – 创建 Bean 。 plugins 插件 - 拦截 CRUD 操作。 environments 环境 -配置数据源 environment 环境变量 transactionManager 事务管理器 JDBC|JNDI|JTA dataSource 数据源 mappers l 映射器 XML 文件| Mapper 类 | 网络资源
- 基础配置文件—环境配置
配置环境
<span style="font-size:12px;"><configuration> <environmentsdefault="development"> <environmentid="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <propertyname="driver" value="$driver"/> <property name="url" value="$url"/> <propertyname="username" value="$username"/> <propertyname="password" value="$password"/> </dataSource> </environment> <environmentid="development2"> …… </environment> </environments> </configuration></span>
- 基础配置文件—事务管理
MyBatis有两种事务管理类型:
l JDBC- 这个类型直接全部使用 JDBC 的提交和回滚功能。它依靠使用连接的数据源来管理事务的作用域。 l MANAGED- 这个类型什么不做, 它从不提交 、 回滚和关闭连接 。 而是让窗口来管理事务的全部生命周期 。(比如说 Spring 或者 JAVAEE 服务器)
- 基础配置文件—数据源
数据源类型有三种:UNPOOLED,POOLED,JNDI。
- UNPOOLED- 这个数据源实现只是在每次请求的时候简单的打开和关闭一个连接。虽然这有点慢,但作为一些不需要性能和立即响应的简单应用来说, 不失为一种好选择 。
- POOLED- 这个数据源缓存 JDBC 连接对象用于避免每次都要连接和生成连接实例而需要的验证时间。对于并发 WEB 应用,这种方式非常流行因为它有最快的响应时间。
- JNDI- 这个数据源实现是为了准备和 Spring 或应用服务一起使用,可以在外部也可以在内部配置这个数据源,然后在 JNDI 上下文中引用它。这个数据源配置只需要两上属性:
- 基础配置文件—SQL映射文件
SQL
映射文件
:
1.使用相对路径
<mappers> <mapper resource="org/mybatis/builder/UserMapper.xml"/> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/> </mappers>
//2.使用全路径<mappers>
<mapper url="file:///var/sqlmaps/AuthorMapper.xml"/>
<mapper url="file:///var/sqlmaps/BlogMapper.xml"/>
<mapper url="file:///var/sqlmaps/PostMapper.xml"/>
</mappers>
2.SQL映射文件
- SQL映射文件结构:(有关文件的增删改查结构将用代码来演示)
cache- 配置给定命名空间的缓存。
cache-ref– 从其他命名空间引用缓存配置。
resultMap – 最复杂,也是最有力量的元素,用来描述如何从数据库结果集中来加载对象。 l
sql – 可以重用的 SQL 块,也可以被其他语句引用。
insert– 映射插入语句
update– 映射更新语句
delete– 映射删除语句
select– 映射查询语句
- 动态SQL MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力 if choose( when,otherwise ) trim( where,set ) foreach
五、核心类的生命周期
- SqlSessionFactoryBuilder的生命周期:这个类可以被初始 、 使用和丢弃 , 如果你已经创建好了一个SqlSessionFactory后就不用再保留它。 因此 ,SqlSessionFactoryBuilder的最好作用域是方法体内,比如说定义一个方法变量。你可以重复使用SqlSessionFactoryBuilder生成多个SqlSessionFactory实例, 但是最好不要强行保留 , 因为 XML 的解析资源要用来做其它更重要的事
- SqlSession 每个线程都有自己的SqlSession实例,SqlSession实例是不能被共享,也是不是线程安全的。因此最好使用Request作用域或者方法体作用域。不要使用类的静态变量来引用一个SqlSession实例,甚至不要使用类的一个实例变更来引用。如果你正在使用WEB框架,应该让SqlSession跟随HTTP请求的相似作用域。也就是说,在收到一个HTTP请求过后,打开SqlSession,等返回一个回应以后,立马关掉这个SqlSession。关闭SqlSession是非常重要的。你必须要确保SqlSession在finally方法体中正常关闭。
- SqlSession 的获取:
package cn.hncu.utils; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; 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 SqlSessionUtil private static SqlSessionFactory ssf;// 底层对应的是Connection连接池 static InputStream in; try in = Resources.getResourceAsStream("mybatis-config.xml");// 从classpath位置加载文件,可以使用相对路径如:cn/hncu/mybatis-config.xml SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder(); ssf=ssfb.build(in); catch (IOException e) e.printStackTrace(); public static SqlSessionFactory getSsf() return ssf; public static SqlSession getSqlSession() return ssf.openSession(); public static void main(String[] args) throws SQLException //SqlSession是Connection的包装类 //每次获取的是不同的SqlSession对象,如果获取一个session对象且从中访问con,则就会到池中去拿一个连接。由于我们在配置文件中设置池大小只有5,因此只有前5个session对象能够顺利取出con对象,第6个session在获取con时会阻塞。 //一个session对象在获取con之后如果不使用,那么超过默认时间,它所持有的con连接会被收回池中。这样其它session对象又可以从池中获取 System.out.println("ssf:"+ssf); //下面这段代码,在5个session获取连接之后会阻塞。过一段时间后,才继续执行6-10个session对象 for(int i=1;i<=10;i++) SqlSession ss=getSqlSession(); System.out.println(i+":sqlSession:"+ss);//sqlSession不同 Connection con=ss.getConnection(); System.out.println(i+":con:"+con);//Connection相同 ss.close();//session对象关闭之后,它所持有的con会还回池中,被下一个session重新持有
mybatis-config.xml的配置是基础的配置
-
SqlSession接口主要方法 新增:
intinsert(String statement, Object parameter)
修改:intupdate(String statement, Object parameter)
删除:intdelete(String statement, Object parameter)
查询:List selectList(String statement, Object parameter)
六、基本使用演示:
##使用前准备:
1).导入log4j-1.2.16.jar,mybatis-3.4.1.jar和mysql-connector-java-5.1.34-bin.jar包
2).在src目录下导入或编写mybatis-config.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>
<typeAliases>
<typeAlias alias="User" type="cn.hncu.domain.User" />
<typeAlias alias="Person" type="cn.hncu.domain.Person" />
<!-- <typeAlias alias="User" type="cn.hncu.domain.UserMapper" /> 如果用namespace不行-->
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql:///mybatis?characterEncoding=utf-8" />
<property name="username" value="root" />
<property name="password" value="1234" />
<property name="poolMaximumActiveConnections" value="5" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="cn/hncu/domain/User.xml" />
<mapper resource="cn/hncu/domain/User2.xml" />
<mapper resource="cn/hncu/domain/Person.xml" />
</mappers>
</configuration>
3).写SqlSessionUtil连接池工具。(用于拿连接)
package cn.hncu.utils;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
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 SqlSessionUtil
private static SqlSessionFactory ssf;// 底层对应的是Connection连接池
static
InputStream in;
try
in = Resources.getResourceAsStream("mybatis-config.xml");// 从classpath位置加载文件,可以使用相对路径如:cn/hncu/mybatis-config.xml
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
ssf=ssfb.build(in);
catch (IOException e)
e.printStackTrace();
public static SqlSessionFactory getSsf()
return ssf;
public static SqlSession getSqlSession()
return ssf.openSession();
public static void main(String[] args) throws SQLException
//SqlSession是Connection的包装类
//每次获取的是不同的SqlSession对象,如果获取一个session对象且从中访问con,则就会到池中去拿一个连接。由于我们在配置文件中设置池大小只有5,因此只有前5个session对象能够顺利取出con对象,第6个session在获取con时会阻塞。
//一个session对象在获取con之后如果不使用,那么超过默认时间,它所持有的con连接会被收回池中。这样其它session对象又可以从池中获取
System.out.println("ssf:"+ssf);
//下面这段代码,在5个session获取连接之后会阻塞。过一段时间后,才继续执行6-10个session对象
for(int i=1;i<=10;i++)
SqlSession ss=getSqlSession();
System.out.println(i+":sqlSession:"+ss);//sqlSession不同
Connection con=ss.getConnection();
System.out.println(i+":con:"+con);//Connection相同
ss.close();//session对象关闭之后,它所持有的con会还回池中,被下一个session重新持有
4)在mybatis数据库中建立表格(利用ant工具)
demo.sql
create database if not exists mybatis default character set 'utf8';
use mybatis;
create table users(
id varchar(32) primary key,
name varchar(32),
pwd varchar(32)
);
insert into users value('U001','Jack','1234');
insert into users value('U010','张三','4321');
CREATE TABLE cpu(
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(30)
);
CREATE TABLE persons(
pid VARCHAR(32) PRIMARY KEY,
pname VARCHAR(30)
);
CREATE TABLE cars(
id VARCHAR(32) PRIMARY KEY,
NAME VARCHAR(30),
price NUMERIC(10,2),
pid VARCHAR(32),
CONSTRAINT car_fk FOREIGN KEY(pid) REFERENCES persons(pid)
);
INSERT INTO persons VALUES('P001','Jack');
INSERT INTO persons VALUES('P002','Rose');
INSERT INTO persons VALUES('P003','张三');
INSERT INTO cars VALUES('C001','BMW',100,'P001');
INSERT INTO cars VALUES('C002','BenZ',80,'P001');
INSERT INTO cars VALUES('C003','Jeep',50,'P003');
CREATE TABLE card(
card_id VARCHAR(32) PRIMARY KEY,
card_gov VARCHAR(30),
pid VARCHAR(32) unique,
CONSTRAINT card_fk FOREIGN KEY(pid) REFERENCES persons(pid)
);
INSERT INTO card VALUES('C001','北京市公安局','P001');
INSERT INTO card VALUES('C002','长沙市公安局','P002');
CREATE TABLE roles(
id VARCHAR(32) PRIMARY KEY,
name VARCHAR(30),
);
CREATE TABLE roleuser(
roleid VARCHAR(32),
userid VARCHAR(32),
CONSTRAINT ru_pk PRIMARY KEY(roleid,userid),
CONSTRAINT ru_fk1 FOREIGN KEY(roleid)
REFERENCES roles(id),
CONSTRAINT ru_fk1 FOREIGN KEY(userid)
REFERENCES users(id)
);
INSERT INTO roles VALUES('R001','教师');
INSERT INTO roles VALUES('R002','老板');
INSERT INTO roles VALUES('R003','学生');
INSERT INTO roleuser VALUES('R001','U001');
INSERT INTO roleuser VALUES('R002','U001');
INSERT INTO roleuser VALUES('R003','U001');
INSERT INTO roleuser VALUES('R001','U010');
INSERT INTO roleuser VALUES('R001','U002');
INSERT INTO roleuser VALUES('R002','U003');
INSERT INTO roleuser VALUES('R002','U003');
5)使用。(建立javaBean)
1.查询:
1)查询学生信息
映射文件
<!--查询的返回结果是一个集合(List),resultType属性设置的是集合中一个元素的类型--> <select id="query1" resultType="User" ><!--用别名来设置返回类型--> select * from users </select>
测试代码:2)查询学生信息(接口方式---推荐方式)@Test//查询学生信息 public void query1() SqlSession s=SqlSessionUtil.getSqlSession(); List<User> list=s.selectList("query1"); System.out.println(list); s.close();//执行之后,最好养成关session的习惯
映射文件
接口代码<!--采用接口的方式访问时,命名空间得取成“接口全名” --> <mapper namespace="cn.hncu.domain.UserMapper"> <!--查询的返回结果是一个集合(List),resultType属性设置的是集合中一个元素的类型--> <select id="query1" resultType="User" ><!--用别名来设置返回类型--> select * from users </select> </mapper>
package cn.hncu.domain; import java.util.List; public interface UserMapper public List<User> query1(); public List<User> queryByID(String string);
测试代码@Test//采用接口的方式访问----mybatis推荐的访问方式 public void queryByInterface() SqlSession s=SqlSessionUtil.getSqlSession(); //与上一版本不同之处---通过接口访问 UserMapper up=s.getMapper(UserMapper.class); List<User> list=up.query1(); System.out.println(list); s.close();
3)查询学生信息(带单个条件)
映射文件
测试代码<!--带条件的查询1:单个条件 助理解:类型方法中的形参:String val --> <select id="queryByID" resultType="User" parameterType="string"> select * from users where 1=1 and id=#val <!-- <if test="id!=null"> and id=#val </if> 不行--> </select>
@Test//带条件的查询1:单个条件 public void queryByID() SqlSession s=SqlSessionUtil.getSqlSession(); //与上一版本不同之处---通过接口访问 List<User> list=s.selectList("queryByID", "U001"); System.out.println(list); s.close();
4)带多条件的查询2:多个条件
映射文件
<!--带条件的查询2:多个条件 注意: sql语句中的参数名必须和值对象中的属性名一致 --> <select id="queryUser" resultType="User" parameterType="User"> select * from users where 1=1 and id=#id <if test="name!=null"> and name like #name </if> </select>
测试代码
@Test//带多条件的查询2:多个条件 public void queryUser() SqlSession s=SqlSessionUtil.getSqlSession(); User user=new User(); user.setId("U001"); user.setName("Jack"); List<User> list=s.selectList("queryUser",user); System.out.println(list);
5)返回结果封装成List<Map>的查询
映射文件
测试代码<select id="queryTOList" resultType="hashmap" parameterType="User"> select * from users </select>
@Test//封装成List<map> public void queryTOList() SqlSession s=SqlSessionUtil.getSqlSession(); List<User> list=s.selectList("queryTOList"); System.out.println(list);
6)返回结果封装成List<Map>的查询 ,条件为hashmap,like查询
映射文件
测试代码<!-- 返回结果封装成List<Map>的查询 ,条件为hashmap--> <select id="queryTOList2" resultType="hashmap" parameterType="hashmap"> select * from users where 1=1 <if test="id!=null"> and id=#id </if> <if test="name!=null"> and name like CONCAT('%','$name','%' ) </if> </select>
@Test//封装成List<map> @Test//查询的输入参数为:HashMap public void queryTOList2() SqlSession s=SqlSessionUtil.getSqlSession(); Map<String, Object> map = new HashMap<String, Object>(); // map.put("id", "U003"); map.put("name", "J"); List<User> list=s.selectList("queryTOList2",map); System.out.println(list);
2.增删改:(一定要提交哦)
1).增:
映射文件
@Test//insert(插入) public void insert() SqlSession s=SqlSessionUtil.getSqlSession(); User user=new User(); user.setId("U005"); user.setName("BGW"); user.setPwd("55555"); s.insert("insert",user); s.commit();//必须显示提交。因为mybatis默认是带事务的即不自动提交 s.close();
测试代码
<insert id="insert" parameterType="User"> insert into users(id,name,pwd) values(#id,#name,#pwd) </insert>
2)单
映射文件
测试代码<delete id="delete" parameterType="hashmap"> delete from users where 1=1 <if test="id!=null"> and id=#id </if> <if test="name!=null"> and name=#name </if> </delete>
@Test//delete删除 public void delete() SqlSession s=SqlSessionUtil.getSqlSession(); Map<String, Object> map = new HashMap<String, Object>(); map.put("id", "U005"); map.put("name", "Jack"); s.delete("delete", map); s.commit();//必须显示提交。因为mybatis默认是带事务的即不自动提交 s.close();
3)更新(修改)
映射文件<update id="update" parameterType="User"> update users set id=#id <if test="name!=null"> , name=#name </if> <if test="pwd!=null"> ,pwd=#pwd </if> where id=#id </update>
测试代码@Test//update更新 public void update() SqlSession s=SqlSessionUtil.getSqlSession(); Map<String, Object> map = new HashMap<String, Object>(); User user=new User(); user.setId("U005"); user.setName("大哥王"); s.update("update",user); s.commit();//必须显示提交。因为mybatis默认是带事务的即不自动提交 s.close();
4)用mybatis调用底层jdbc实现自动生成主键
映射文件
测试代码<!-- 用mybatis调用底层jdbc实现自动生成主键 --> <insert id="generateKey2" parameterType="hashmap" keyProperty="id" keyColumn="id" useGeneratedKeys="true" > insert into cpu(name) values(#name) </insert>
//mybatis中实现自动生成主键 @Test//底层jdbc的方式 public void generateKey1() throws SQLException SqlSession s=SqlSessionUtil.getSqlSession(); Connection con=s.getConnection(); PreparedStatement pst=con.prepareStatement("insert into cpu(name) values(?)",Statement.RETURN_GENERATED_KEYS); pst.setString(1, "ibm"); int a=pst.executeUpdate(); ResultSet rs=pst.getGeneratedKeys(); rs.next(); s.commit(); s.close(); System.out.println(rs.getInt(1)); @Test//mybatis的方式 public void generateKey2() throws SQLException SqlSession s=SqlSessionUtil.getSqlSession(); Map<String, Object> map=new HashMap<String, Object>(); map.put("name", "intel"); int n=s.insert("generateKey2",map); System.out.println(n); //n是影响的行数 System.out.println(map.get("id")); s.commit(); s.close();
3.复杂操作和标签的操作(m命名空间为user,基础配置文件是原来的)
1)多条件查询
映射文件
2)where标签的使用<select id="dyncUser1" resultType="User" parameterType="User"> select * from users where 1=1 <if test="id!=null"> and id=#id </if> <if test="pwd!=null"> and pwd like #pwd </if> <if test="name!=null"> and name like #name </if> </select>
映射文件
3)trim标签的使用<select id="dyncUser2" resultType="User" parameterType="User"> select * from users <!-- 用where标签代替上一版本的: where 1=1 --> <where> <if test="id!=null"> and id=#id<!-- 解析时第一个and会去掉 --> </if> <if test="pwd!=null"> and pwd like #pwd </if> <if test="name!=null"> and name like #name </if> </where> </select>
映射文件
4)set标签的使用<!-- trim的使用 --> <select id="dyncUser3" resultType="User" parameterType="User"> select * from users <!-- 用前缀“where”去覆盖第一个子句中的“and”或“or” --> <trim prefix="where" prefixOverrides="and|or"> <if test="id!=null"> and id=#id </if> <if test="pwd!=null"> and pwd like #pwd </if> <if test="name!=null"> and name like #name </if> </trim> </select>
映射文件<!-- 使用set标签进行更新记录 --> <update id="dyncUpdate" parameterType="User"> update users <set> <if test="name!=null"> name=#name </if> <if test="pwd!=null"> pwd=#pwd </if> </set> where id=#id </update>
5)foreach标签的使用
映射文件
测试代码<!-- for each执行的效果: ('U001','U002','U010') 相间查询 --> <select id="dyncUser4" resultType="User" parameterType="list"> select * from users <if test="list!=null and list.size()>0"> where id in <foreach collection="list" index="idx" item="val" open="(" close=")" separator=","> #val </foreach> </if> </select>
package cn.hncu.demo; import java.util.ArrayList; import java.util.List; import org.apache.ibatis.session.SqlSession; import org.junit.Test; import cn.hncu.domain.User; import cn.hncu.utils.SqlSessionUtil; public class Demo2 @Test public void query() SqlSession s = SqlSessionUtil.getSqlSession(); User u = new User(); // u.setId("U001"); u.setName("%Jack%"); // u.setPwd("%1%"); // List<User> list=s.selectList("user.dyncUser1", u); // List<User> list=s.selectList("user.dyncUser2", u); List<User> list=s.selectList("user.dyncUser3", u); System.out.println(list); @Test public void update() SqlSession s = SqlSessionUtil.getSqlSession(); User u = new User(); u.setId("U005"); u.setName("Tom"); // u.setPwd("1565"); s.update("dyncUpdate",u); s.commit(); s.close(); @Test public void queryForeach() SqlSession s = SqlSessionUtil.getSqlSession(); List<Object> list=new ArrayList<Object>(); list.add("U001"); list.add("U005"); list=s.selectList("dyncUser4", list); System.out.println(list); s.close();
5.多表操作(namespace="person")
1)一对多查询操作
法1映射文件(内连接)法2映射文件(左外连接)<!-- 一对多:法1 --> <!--用resultMap来定义一个:自定义复杂结果类型 。注意,column指的是查询结果集中的字段别名--> <resultMap type="Person" id="ps"><!-- 这里的colum都是查询出来的表的column --> <id property="id" column="pid"/> <result property="name" column="pname"/> <collection property="cars" javaType="cn.hncu.domain.Car"> <id property="id" column="cid"/> <result property="name" column="cname" javaType="string" jdbcType="VARCHAR"/> <result property="price" column="cprice" javaType="double" jdbcType="NUMERIC"/> </collection> </resultMap> <!-- resultType只能用于定义简单类型。要通过resultMap来定义一个:自定义复杂结果类型 --> <!-- 此处是引用上面定义的复杂结果类型 --> <select id="person1" resultMap="ps"> select p.pid as pid,p.pname as pname,c.id as cid,c.name as cname from persons p inner join cars c on p.pid=c.pid </select>
<!-- 一对多:法2 (效果为left join),子查询或嵌套查询 --> <select id="car1" resultType="cn.hncu.domain.Car" parameterType="string"> select *from cars where pid=#pid </select> <resultMap type="Person" id="ps2"> <id column="pid" property="id"/> <result property="name" column="pname"/> <collection property="cars" select="car1" column="pid"></collection> </resultMap> <select id="person2" resultMap="ps2"> select pid,pname from persons <!-- 这里的pname结果无效 --> </select>
测试文件
//内联: 查询哪些人有哪些车 @Test public void query() SqlSession s = SqlSessionUtil.getSqlSession(); // List<Person> persons = s.selectList("person.person1"); List<Person> persons = s.selectList("person.person2"); System.out.println(persons); s.close();
2.一对一的多表查询
映射文件测试文件<!-- 以下演示一对一关系 --> <!-- 同理,下面字段名都是别名 --> <resultMap type="cn.hncu.domain.Card" id="c1"> <!-- <id property="id" column="id"/> 可以--> <constructor> <idArg column="id" javaType="string"/> </constructor> <result property="gov" column="gov" javaType="string" jdbcType="VARCHAR"/> <association property="person" javaType="Person"> <!-- mybatis建议使用id,这里只是展示用result也可以,但性能有差别 --> <id property="id" column="pid"/> <result property="name" column="pname"/> <collection property="cars" select="car1" column="pid"> </collection> </association> </resultMap> <select id="card" resultMap="c1"> SELECT c.card_id AS id,c.card_gov AS gov ,p.pid AS pid,p.pname AS pname FROM card c INNER JOIN persons p ON c.pid = p.pid </select>
3.多对多的多表查询一对一 @Test public void queryCard() SqlSession s = SqlSessionUtil.getSqlSession(); List<Card> cards = s.selectList("person.card"); System.out.println(cards); s.close();
映射文件<mapper namespace="role"> <!-- 多对多演示 --> <resultMap type="User" id="ms" > <id property="id" column="uid"/> <result property="name" column="uname"/> <result property="pwd" column="pwd"/> <collection property="roles" javaType="cn.hncu.domain.Role"> <id property="id" column="uid"/> <result property="name" column="关系"/> </collection> </resultMap> <select id="mutilSelect" resultMap="ms"> SELECT u.id AS uid, u.name AS uname,u.pwd AS pwd,r.id AS rid,r.name AS 关系 FROM users u INNER JOIN roleuser ru ON u.id=ru.userid INNER JOIN roles r ON r.id=ru.roleid </select> </mapper>
测试代码/ 多对多 @Test public void mutilSelect() SqlSession s = SqlSessionUtil.getSqlSession(); List<User> user = s.selectList("role.mutilSelect"); System.out.println(user); s.close();
5.其他操作
1)sql代码片段(include标签的使用)
<!-- sql片段/ --> <sql id="sql1"> id,name,pwd </sql> <select id="queryBySql" resultType="User"> select <include refid="sql1"/> from users </select>
2)缓存机制:mybatis和hibernate一样,有两级缓存,第一级是session级别的缓存,第二级是二级缓存
一级缓存演示:
<select id="one" parameterType="string" resultType="cn.hncu.domain.Role" > select *from roles where id=#id </select>
测试代码:
以上是关于JavaEE框架——Mybatis入门和和使用(增删改查,缓存)的主要内容,如果未能解决你的问题,请参考以下文章JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD
JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD
JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD
杨老师课堂之JavaEE三大框架Hibernate入门教程第一课