基础 入门 平时我们都用JDBC访问数据库,除了需要自己写SQL之外,还必须操作Connection, Statement, ResultSet 这些其实只是手段的辅助类。 不仅如此,访问不同的表,还会写很多雷同的代码,显得繁琐和枯燥。
那么用了Mybatis之后,只需要自己提供SQL语句,其他的工作,诸如建立连接,Statement, JDBC相关异常处理等等都交给Mybatis去做了,那些重复性的工作Mybatis也给做掉了,我们只需要关注在增删改查等操作层面上,而把技术细节都封装在了我们看不见的地方。
创建数据库
1 create database how2java
创建表
1 2 3 4 5 6 7 USE how2java; CREATE TABLE category_ ( id int (11 ) NOT NULL AUTO_INCREMENT, name varchar (32 ) DEFAULT NULL , PRIMARY KEY (id) ) ENGINE= MyISAM AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8;
导入数据
1 2 3 USE how2java; INSERT INTO category_ VALUES (null ,'category1' );INSERT INTO category_ VALUES (null ,'category2' );
上面数据库的三步完成后截图:
创建项目
e:\project\mybatis
导包
C:\Users\hahaha\Desktop\计算机\spring\mybatis_experiment_HOW2J\lib
创建实体类
准备实体类Category,用于映射表category_
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.how2java.pojo; public class Category { private int id; private String name; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } }
配置文件mybatis-config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <?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 > <package name ="com.how2java.pojo" /> </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://localhost:3306/how2java?characterEncoding=UTF-8" /> <property name ="username" value ="root" /> <property name ="password" value ="admin" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="com/how2java/pojo/Category.xml" /> </mappers > </configuration >
解释:
在src目录下创建mybatis的主配置文件mybatis-config.xml (相当于hibernate.cfg.xml,如果没有hibernate基础请忽略本句)。 其作用主要是提供连接数据库用的驱动,数据库名称,编码方式,账号密码
1 2 3 4 <property name ="driver" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/how2java?characterEncoding=UTF-8" /> <property name ="username" value ="root" /> <property name ="password" value ="admin" />
以及别名,自动扫描com.how2java.pojo下的类型 ,使得在后续配置文件Category.xml 中使用resultType的时候,可以直接使用Category,而不必写全com.how2java.pojo.Category
1 2 3 <typeAliases > <package name ="com.how2java.pojo" /> </typeAliases >
映射Category.xml
1 2 3 <mappers > <mapper resource ="com/how2java/pojo/Category.xml" /> </mappers >
配置文件Category.xml
在包com.how2java.pojo下,新建文件Category.xml
1 2 3 4 5 6 7 8 9 10 <?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 ="com.how2java.pojo" > <select id ="listCategory" resultType ="Category" > select * from category_ </select > </mapper >
解释:
表示命名空间是com.how2java.pojo,在后续调用sql语句的时候,会用到它
1 namespace="com.how2java.pojo"
里面定义了一条sql语句
这条sql语句用id: listCategory 进行标示以供后续代码调用。resultType=”Category” 表示返回的是一个Category类型的对象,里面就有在数据库里面查询出来的值,这里本应该使用的是 com.how2java.pojo.Category, 但是因为上一步配置了别名(自动扫描com.how2java.pojo下面的类型),所以直接使用Category就行了
1 2 3 <select id ="listCategory" resultType ="Category" > select * from category_ </select >
测试类TestMybatis
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package com.how2java;import java.io.IOException;import java.io.InputStream;import java.util.List;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import com.how2java.pojo.Category;public class TestMybatis { public static void main (String[] args) throws IOException { String resource = "mybatis-config.xml" ; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ().build(inputStream); SqlSession session=sqlSessionFactory.openSession(); List<Category> cs=session.selectList("listCategory" ); for (Category c : cs) { System.out.println(c.getName()); } } }
基本原理图
应用程序找Mybatis要数据
mybatis从数据库中找来数据 2.1 通过mybatis-config.xml 定位哪个数据库 2.2 通过Category.xml执行对应的select语句 2.3 基于Category.xml把返回的数据库记录封装在Category对象中 2.4 把多个Category对象装在一个Category集合中
返回一个Category集合
CRUD(增删改查) 配置文件Category.xml
首先一次性修改配置文件Category.xml,提供CRUD对应的sql语句。 每个SQL如何使用在后续对应操作里一一讲解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 <?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 ="com.how2java.pojo" > <insert id ="addCategory" parameterType ="Category" > insert into category_ ( name ) values (#{name}) </insert > <delete id ="deleteCategory" parameterType ="Category" > delete from category_ where id= #{id} </delete > <select id ="getCategory" parameterType ="_int" resultType ="Category" > select * from category_ where id= #{id} </select > <update id ="updateCategory" parameterType ="Category" > update category_ set name=#{name} where id=#{id} </update > <select id ="listCategory" resultType ="Category" > select * from category_ </select > </mapper >
增加
addCategory对应的插入sql语句,#{name}会自动获取c对象的name属性值
1 2 3 4 5 <mapper namespace ="com.how2java.pojo" > <insert id ="addCategory" parameterType ="Category" > insert into category_ ( name ) values (#{name}) </insert > </mapper >
通过session.insert调用addCategory对应的SQL语句
1 2 3 Category c = new Category ();c.setName("新增加的Category" ); session.insert("addCategory" ,c);
测试类,增加后再遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.how2java;import java.io.IOException;import java.io.InputStream;import java.util.List;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import com.how2java.pojo.Category;public class TestMybatis { public static void main (String[] args) throws IOException { String resource = "mybatis-config.xml" ; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); Category c = new Category (); c.setName("新增加的Category" ); session.insert("addCategory" ,c); listAll(session); session.commit(); session.close(); } private static void listAll (SqlSession session) { List<Category> cs = session.selectList("listCategory" ); for (Category c : cs) { System.out.println(c.getName()); } } }
结果:增加了一条数据进去
删除
删除id=6的对象
1 2 3 Category c = new Category ();c.setId(6 ); session.delete("deleteCategory" ,c);
deleteCategory对应删除的sql语句,#{id}会自动获取c对象的id属性值
1 2 3 <delete id ="deleteCategory" parameterType ="Category" > delete from category_ where id= #{id} </delete >
结果:
获取
通过session.selectOne获取id=3的记录
1 Category c= session.selectOne("getCategory" ,3 );
getCategory对应的sql语句:
1 2 3 <select id ="getCategory" parameterType ="_int" resultType ="Category" > select * from category_ where id= #{id} </select >
修改
通过session.update进行修改
1 2 3 Category c= session.selectOne("getCategory" ,3 ); c.setName("修改了的Category名稱" ); session.update("updateCategory" ,c);
updateCategory对应的sql语句:
1 2 3 <update id ="updateCategory" parameterType ="Category" > update category_ set name=#{name} where id=#{id} </update >
查询所有
session.selectList执行查询语句
1 2 3 4 5 6 private static void listAll (SqlSession session) { List<Category> cs = session.selectList("listCategory" ); for (Category c : cs) { System.out.println(c.getName()); } }
listCategory对应的sql语句
1 2 3 <select id ="listCategory" resultType ="Category" > select * from category_ </select >
MyBatis的传入参数parameterType类型分两种
基本数据类型:int,string,long,Date;
复杂数据类型:类和Map
如何获取参数中的值:
2.1 基本数据类型:#{value}或${value} 获取参数中的值
2.2 复杂数据类型:#{属性名}或${属性名} ,map中则是#{key}或${key}
resultType:
1、基本类型 :resultType=基本类型
2、List类型: resultType=List中元素的类型
3、Map类型: 单条记录:resultType =map
多条记录:resultType =Map中value的类型
parameterType 指定输入参数类型,mybatis 通过 ognl 从输入对象中获取参数值拼接在 sql 中。
resultType 指定输出结果类型,mybatis 将 sql 查询结果的一行记录数据映射为 resultType 指定类型的对象。如果有多条数据,则分别进行映射,并把对象放到容器List中。
selectOne 查询一条记录,如果使用 selectOne 查询多条记录则抛出异常。
selectList 可以查询一条或多条记录,返回一个 List 集合。
更多查询 模糊查询
修改Category.xml,提供listCategoryByName查询语句
1 2 3 <select id ="listCategoryByName" parameterType ="string" resultType ="Category" > select * from category_ where name like concat('%',#{0},'%') </select >
测试类由List<Category> cs = session.selectList("listCategory");
变为List<Category> cs = session.selectList("listCategoryByName","cat");
解释:
SQL语句中:
CONCAT 关键字:把字符串拼接到一起
LIKE 关联字:模糊匹配 。”%” 可用于定义通配符(模式中缺少的字母)。
参数解释: like concat(’%/’,#{datePath,jdbcType=VARCHAR},’/%’)
concat函数:
第一个参数 ,就是'%',其中%后边可以加上一些常量字符比如 / 。
第二参数,基本上就是传递过来的参数 。
第三个参数,是结尾的 '%', %前边可以加一定的常量字符比如 / 。
出现了cat的字符串都输出了:
多条件查询
结合前面的模糊查询,多一个id>多少的条件 Category.xml 准备sql语句
1 2 3 <select id ="listCategoryByIdAndName" parameterType ="map" resultType ="Category" > select * from category_ where id> #{id} and name like concat('%',#{name},'%') </select >
测试代码 因为是多个参数,而selectList方法又只接受一个参数对象,所以需要把多个参数放在Map里,然后把这个Map对象作为参数传递进去
1 2 3 4 5 6 7 8 Map<String,Object> params = new HashMap <>(); params.put("id" , 3 ); params.put("name" , "cat" ); List<Category> cs = session.selectList("listCategoryByIdAndName" ,params); for (Category c : cs) { System.out.println(c.getName()); }
解释模糊查询的逻辑:session(会话)
Test.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 String resource = "mybatis-config.xml" ; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); List<Category> cs = session.selectList("listCategoryByName" ,"cat" ); for (Category c : cs) { System.out.println(c.getName()); } session.commit(); session.close();
一对多 表结构
分类表不变化,新增加产品表
1 2 3 4 5 6 7 8 use how2java; create table product_(id int NOT NULL AUTO_INCREMENT, name varchar (30 ) DEFAULT NULL , price float DEFAULT 0 , cid int , PRIMARY KEY (id))AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8;
准备数据
清空category_ 和 product_ 表 新增2条分类数据,id分别是1,2 新增6条产品数据,分别关联上述2条分类数据
1 2 3 4 5 6 7 8 9 10 11 use how2java; delete from category_;INSERT INTO category_ VALUES (1 ,'category1' );INSERT INTO category_ VALUES (2 ,'category2' );delete from product_;INSERT INTO product_ VALUES (1 ,'product a' , 88.88 , 1 );INSERT INTO product_ VALUES (2 ,'product b' , 88.88 , 1 );INSERT INTO product_ VALUES (3 ,'product c' , 88.88 , 1 );INSERT INTO product_ VALUES (4 ,'product x' , 88.88 , 2 );INSERT INTO product_ VALUES (5 ,'product y' , 88.88 , 2 );INSERT INTO product_ VALUES (6 ,'product z' , 88.88 , 2 );
Product实体类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.how2java.pojo;public class Product { private int id; private String name; private float price; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public float getPrice () { return price; } public void setPrice (float price) { this .price = price; } @Override public String toString () { return "Product [id=" + id + ", name=" + name + ", price=" + price + "]" ; } }
修改Category实体类
修改Category实体类,提供products的集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package com.how2java.pojo; import java.util.List; public class Category { private int id; private String name; List<Product> products; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public List<Product> getProducts () { return products; } public void setProducts (List<Product> products) { this .products = products; } @Override public String toString () { return "Category [id=" + id + ", name=" + name + "]" ; } }
暂时无需 Product.xml
本例演示通过分类对产品的一对多,暂时无需 Product.xml
修改Category.xml
通过left join关联查询,对Category和Product表进行关联查询。 与前面学习的有所区别,这里不是用的resultType, 而是resultMap,通过resultMap把数据取出来放在对应的 对象属性里注 : Category的id 字段 和Product的id字段同名,Mybatis不知道谁是谁的,所以需要通过取别名cid,pid来区分。 name字段同理。
我的理解:
resultMap是用来给返回的结果起别名的,其映射是property和column的映射,
比如说<id column="cid" property="id" />
的意思就是,key是属性id,值是数据库中取出来的cid,cid就是数据库中c.id的别名
而<result column="price" property="price" />
因为属性price和数据库中的列price名字一样,所以没有起别名,直接把属性price作为key,取出value,也就是数据库中的price
这里也可以看出取别名的过程,将category_表取名为c,将product__表取名为p。将c.id列取名为cid,将p.id列取名为pid
select c.*, p.*, c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname' from category_ c left join product_ p on c.id = p.cid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <mapper namespace ="com.how2java.pojo" > <resultMap type ="Category" id ="categoryBean" > <id column ="cid" property ="id" /> <result column ="cname" property ="name" /> <collection property ="products" ofType ="Product" > <id column ="pid" property ="id" /> <result column ="pname" property ="name" /> <result column ="price" property ="price" /> </collection > </resultMap > <select id ="listCategory" resultMap ="categoryBean" > select c.*, p.*, c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname' from category_ c left join product_ p on c.id = p.cid </select > </mapper >
测试运行TestMybatis
1 2 3 4 5 6 7 8 List<Category> cs = session.selectList("listCategory" ); for (Category c : cs) { System.out.println(c); List<Product> ps = c.getProducts(); for (Product p : ps) { System.out.println("\t" +p); } }
结果:
一对多 修改Product.java
为Product增加category属性
1 2 3 4 5 6 7 8 private Category category; public Category getCategory () { return category; } public void setCategory (Category category) { this .category = category; }
Product.xml
提供Product.xml,通过listProduct配置关联查询的sql语句。 然后通过resultMap ,进行字段和属性的对应。 使用association 进行多对一关系关联,指定表字段名称与对象属性名称的一一对应关系注: Category的id 字段 和Product的id字段同名,Mybatis不知道谁是谁的,所以需要通过取别名cid,pid来区分。 name字段同理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <mapper namespace ="com.how2java.pojo" > <resultMap type ="Product" id ="productBean" > <id column ="pid" property ="id" /> <result column ="pname" property ="name" /> <result column ="price" property ="price" /> <association property ="category" javaType ="Category" > <id column ="cid" property ="id" /> <result column ="cname" property ="name" /> </association > </resultMap > <select id ="listProduct" resultMap ="productBean" > select c.*, p.*, c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname' from category_ c left join product_ p on c.id = p.cid </select > </mapper >
mybatis-config.xml
在mybatis-config.xml中增加对于Product.xml的映射
1 2 3 4 <mappers > <mapper resource ="com/how2java/pojo/Category.xml" /> <mapper resource ="com/how2java/pojo/Product.xml" /> </mappers >
TestMybatis
1 2 3 4 List<Product> ps = session.selectList("listProduct" ); for (Product p : ps) { System.out.println(p+" 对应的分类是 \t " + p.getCategory()); }
结果:
多对多 定义多对多关系
本知识点是基于多对一 的基础上进行。 在学习之前首先要理清楚多对多的关系,这里以订单Order和产品Product为例: 一张订单里 可以包含多种产品 一种产品 可以出现在多张订单里 这就是多对多关系 为了维系多对多关系,必须要一个中间表。 在这里我们使用订单项(OrderItem)表来作为中间表
表结构
1 2 3 4 5 6 7 8 9 10 11 12 13 create table order_ ( id int (11 ) NOT NULL AUTO_INCREMENT, code varchar (32 ) DEFAULT NULL , PRIMARY KEY (id) ) ENGINE= MyISAM AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8; create table order_item_( id int (11 ) NOT NULL AUTO_INCREMENT, oid int , pid int , number int , PRIMARY KEY(id) )AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8;
导入数据
在一对多关系中准备的数据 里已经有Product数据里,这里就只准备订单数据和订单项数据:
插入两个订单
插入6条订单项数据,建立如下关系 2.1 订单1对应产品 1,2,3 2.2 订单2对应产品 2,3,4
1 2 3 4 5 6 7 8 9 INSERT INTO order_ VALUES (1 ,'code000A' );INSERT INTO order_ VALUES (2 ,'code000B' ); INSERT INTO order_item_ VALUES (null , 1 , 1 , 100 );INSERT INTO order_item_ VALUES (null , 1 , 2 , 100 );INSERT INTO order_item_ VALUES (null , 1 , 3 , 100 );INSERT INTO order_item_ VALUES (null , 2 , 2 , 100 );INSERT INTO order_item_ VALUES (null , 2 , 3 , 100 );INSERT INTO order_item_ VALUES (null , 2 , 4 , 100 );
实体类
实体类Order和OrderItem
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.how2java.pojo; public class OrderItem { private int id; private int number; private Order order; private Product product; public int getId () { return id; } public void setId (int id) { this .id = id; } public int getNumber () { return number; } public void setNumber (int number) { this .number = number; } public Order getOrder () { return order; } public void setOrder (Order order) { this .order = order; } public Product getProduct () { return product; } public void setProduct (Product product) { this .product = product; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.how2java.pojo; import java.util.List; public class Order { private int id; private String code; List<OrderItem> orderItems; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getCode () { return code; } public void setCode (String code) { this .code = code; } public List<OrderItem> getOrderItems () { return orderItems; } public void setOrderItems (List<OrderItem> orderItems) { this .orderItems = orderItems; } }
映射文件Order.xml
后续会解释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <?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 ="com.how2java.pojo" > <resultMap type ="Order" id ="orderBean" > <id column ="oid" property ="id" /> <result column ="code" property ="code" /> <collection property ="orderItems" ofType ="OrderItem" > <id column ="oiid" property ="id" /> <result column ="number" property ="number" /> <association property ="product" javaType ="Product" > <id column ="pid" property ="id" /> <result column ="pname" property ="name" /> <result column ="price" property ="price" /> </association > </collection > </resultMap > <select id ="listOrder" resultMap ="orderBean" > select o.*,p.*,oi.*, o.id 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname' from order_ o left join order_item_ oi on o.id =oi.oid left join product_ p on p.id = oi.pid </select > <select id ="getOrder" resultMap ="orderBean" > select o.*,p.*,oi.*, o.id 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname' from order_ o left join order_item_ oi on o.id =oi.oid left join product_ p on p.id = oi.pid where o.id = #{id} </select > </mapper >
映射文件Product.xml
后续会解释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 <?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 ="com.how2java.pojo" > <resultMap type ="Product" id ="productBean" > <id column ="pid" property ="id" /> <result column ="pname" property ="name" /> <result column ="price" property ="price" /> <association property ="category" javaType ="Category" > <id column ="cid" property ="id" /> <result column ="cname" property ="name" /> </association > </resultMap > <select id ="listProduct" resultMap ="productBean" > select c.*, p.*, c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname' from category_ c left join product_ p on c.id = p.cid </select > <select id ="getProduct" resultMap ="productBean" > select c.*, p.*, c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname' from category_ c left join product_ p on c.id = p.cid where p.id = #{id} </select > </mapper >
映射文件OrderItem.xml
后续会解释
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?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 ="com.how2java.pojo" > <insert id ="addOrderItem" parameterType ="OrderItem" > insert into order_item_ values(null,#{order.id},#{product.id},#{number}) </insert > <insert id ="deleteOrderItem" parameterType ="OrderItem" > delete from order_item_ where oid = #{order.id} and pid = #{product.id} </insert > </mapper >
修改mybatis-config.xml
添加对于Order.xml和OrderItem的映射
1 2 3 4 5 6 <mappers > <mapper resource ="com/how2java/pojo/Category.xml" /> <mapper resource ="com/how2java/pojo/Product.xml" /> <mapper resource ="com/how2java/pojo/Order.xml" /> <mapper resource ="com/how2java/pojo/OrderItem.xml" /> </mappers >
查询操作
如图所示,查询出所有的订单,然后遍历每个订单下的多条订单项,以及订单项对应的产品名称,价格,购买数量
通过Order.xml的listOrder对应的sql语句进行查询:
1 2 3 4 5 6 <select id ="listOrder" resultMap ="orderBean" > select o.*,p.*,oi.*, o.id 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname' from order_ o left join order_item_ oi on o.id =oi.oid left join product_ p on p.id = oi.pid </select >
联合order_ , order_item_, product_ 三张表进行查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <resultMap type ="Order" id ="orderBean" > <id column ="oid" property ="id" /> <result column ="code" property ="code" /> <collection property ="orderItems" ofType ="OrderItem" > <id column ="oiid" property ="id" /> <result column ="number" property ="number" /> <association property ="product" javaType ="Product" > <id column ="pid" property ="id" /> <result column ="pname" property ="name" /> <result column ="price" property ="price" /> </association > </collection > </resultMap >
建立关系
如图所示,建立了让订单000A和产品z建立了关系 首先通过id分别获取Order对象和Product对象,然后创建一个新的OrderItem对象,接着设置Order,设置Product,设置数量,最后调用”addOrderItem” 对应的sql语句插入数据。
1 2 3 4 5 6 7 Order o1 = session.selectOne("getOrder" , 1 );Product p6 = session.selectOne("getProduct" , 6 );OrderItem oi = new OrderItem ();oi.setProduct(p6); oi.setOrder(o1); oi.setNumber(200 ); session.insert("addOrderItem" , oi);
addOrderItem调用insert into 语句插入一条OrderItem记录
1 2 3 4 <insert id ="addOrderItem" parameterType ="OrderItem" > insert into order_item_ values(null,#{order.id},#{product.id},#{number}) </insert >
删除关系
如图所示,删除了订单00A和产品z的关系,再次查询,就看不到产品z了。 删除关系的时候,通过订单id(1)和产品id(6)进行删除。 其实所谓的删除关系,就是删除掉OrderItem记录。
1 2 3 4 5 6 Order o1 = session.selectOne("getOrder" ,1 );Product p6 = session.selectOne("getProduct" ,6 );OrderItem oi = new OrderItem ();oi.setProduct(p6); oi.setOrder(o1); session.delete("deleteOrderItem" , oi);
修改关系
多对多不存在修改关系的做法,就是删除旧的,然后新增一条即达到修改的效果。
注解 CRUD Mapper接口
新增加接口CategoryMapper ,并在接口中声明的方法上,加上注解 对比配置文件Category.xml ,其实就是把SQL语句从XML挪到了注解上来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.how2java.mapper;import java.util.List;import org.apache.ibatis.annotations.Delete;import org.apache.ibatis.annotations.Insert;import org.apache.ibatis.annotations.Select;import org.apache.ibatis.annotations.Update;import com.how2java.pojo.Category;public interface CategoryMapper { @Insert(" insert into category_ ( name ) values (#{name}) ") public int add (Category category) ; @Delete(" delete from category_ where id= #{id} ") public void delete (int id) ; @Select("select * from category_ where id= #{id} ") public Category get (int id) ; @Update("update category_ set name=#{name} where id=#{id} ") public int update (Category category) ; @Select(" select * from category_ ") public List<Category> list () ; }
mybatis-config.xml
1 2 3 <mappers > <mapper class ="com.how2java.mapper.CategoryMapper" /> </mappers >
测试类
进行CRUD的经典操作,来测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 public class TestMybatis { public static void main (String[] args) throws IOException { String resource = "mybatis-config.xml" ; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); CategoryMapper mapper = session.getMapper(CategoryMapper.class); listAll(mapper); session.commit(); session.close(); } private static void update (CategoryMapper mapper) { Category c= mapper.get(8 ); c.setName("修改了的Category名称" ); mapper.update(c); listAll(mapper); } private static void get (CategoryMapper mapper) { Category c= mapper.get(8 ); System.out.println(c.getName()); } private static void delete (CategoryMapper mapper) { mapper.delete(2 ); listAll(mapper); } private static void add (CategoryMapper mapper) { Category c = new Category (); c.setName("新增加的Category" ); mapper.add(c); listAll(mapper); } private static void listAll (CategoryMapper mapper) { List<Category> cs = mapper.list(); for (Category c : cs) { System.out.println(c.getName()); } } }
一对多 CategoryMapper
新增加CategoryMapper接口,查询所有Category @Select注解获取Category类本身
1 @Select(" select * from category_ ")
@Results 通过@Result和@Many中调用ProductMapper.listByCategory()方法相结合,来获取一对多关系
1 2 @Results({@Result(property = "products", javaType = List.class, column = "id", many = @Many(select = "com.how2java.mapper.ProductMapper.listByCategory"))})
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public interface CategoryMapper { @Select(" select * from category_ ") @Results({ @Result(property = "id", column = "id"), // property:指定将关联查询的结果封装到Category对象的List<Product> products属性上 // javaType返回值类型是一个List // column:指定在执行@Many注解中定义的select语句时,把category表的id字段当做参数传入 // many:指定通过@Many注解定义关联查询的语句是ProductMapper中的listByCategory方法 @Result(property = "products", javaType = List.class, column = "id", many = @Many(select = "com.how2java.mapper.ProductMapper.listByCategory") ) }) public List<Category> list () ; }
ProductMapper
新增接口ProductMapper 注解@Select用于根据分类id获取产品集合 @Select(“ select * from product_ where cid = #{cid}”)
1 2 3 4 public interface ProductMapper { @Select(" select * from product_ where cid = #{cid}") public List<Product> listByCategory (int cid) ; }
mybatis-config.xml
添加ProductMapper和CategoryMapper的映射
1 2 3 4 <mappers > <mapper class ="com.how2java.mapper.CategoryMapper" /> <mapper class ="com.how2java.mapper.ProductMapper" /> </mappers >
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public class TestMybatis { public static void main (String[] args) throws IOException { String resource = "mybatis-config.xml" ; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); CategoryMapper mapper = session.getMapper(CategoryMapper.class); listAll(mapper); session.commit(); session.close(); } private static void listAll (CategoryMapper mapper) { List<Category> cs = mapper.list(); for (Category c : cs) { System.out.println(c.getName()); List<Product> ps = c.getProducts(); for (Product p : ps) { System.out.println("\t" +p.getName()); } } } }
多对一 CategoryMapper
新增CategoryMapper接口,提供get方法
1 2 3 4 public interface CategoryMapper { @Select(" select * from category_ where id = #{id}") public Category get (int id) ; }
ProductMapper
新增ProductMapper接口,提供list方法
1 2 3 4 5 6 7 public interface ProductMapper { @Select(" select * from product_ ") @Results({ @Result(property="category",column="cid",one=@One(select="com.how2java.mapper.CategoryMapper.get")) }) public List<Product> list () ; }
测试类
1 2 3 4 List<Product> ps= mapper.list(); for (Product p : ps) { System.out.println(p + "\t对应的分类是:\t" + p.getCategory().getName()); }
多对多 ProductMapper
新增一个ProductMapper接口,提供 get方法
1 2 3 4 public interface ProductMapper { @Select("select * from product_ where id = #{id}") public Product get (int id) ; }
OrderItemMapper
新增OrderItemMapper,提供listByOrder方法。 这里会与Product建立多对一关系
1 2 3 4 5 6 7 public interface OrderItemMapper { @Select(" select * from order_item_ where oid = #{oid}") @Results({ @Result(property="product",column="pid",one=@One(select="com.how2java.mapper.ProductMapper.get")) }) public List<OrderItem> listByOrder (int oid) ; }
OrderMapper
新增OrderMapper,提供list方法,这里会与OrderItem建立一对多关系
1 2 3 4 5 6 7 8 9 public interface OrderMapper { @Select("select * from order_") @Results({ @Result(property = "id", column = "id"), @Result(property = "orderItems", javaType = List.class, column = "id", many = @Many(select = "com.how2java.mapper.OrderItemMapper.listByOrder")) }) public List<Order> list () ; }
修改mybatis-config.xml
新增Mapper类的映射
1 2 3 4 5 6 <mappers > <mapper resource ="com/how2java/pojo/OrderItem.xml" /> <mapper class ="com.how2java.mapper.OrderItemMapper" /> <mapper class ="com.how2java.mapper.OrderMapper" /> <mapper class ="com.how2java.mapper.ProductMapper" /> </mappers >
查询测试
如图所示,运行测试遍历所有的订单,再通过一对多和多对一,间接地多对多遍历出产品。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 private static void listOrder (SqlSession session) { OrderMapper mapper = session.getMapper(OrderMapper.class); List<Order> os = mapper.list(); for (Order o : os) { System.out.println(o.getCode()); List<OrderItem> ois= o.getOrderItems(); if (null !=ois){ for (OrderItem oi : ois) { System.out.format("\t%s\t%f\t%d%n" , oi.getProduct().getName(),oi.getProduct().getPrice(),oi.getNumber()); } } } }