一、更多查询
1.模糊查询
修改Category.xml,提供listCategoryByName查询语句select * from category where name like concat('%',#{0},'%')。concat('%',#{0},'%') 这是mysql的写法,如果是oracle,写法是select * from category_ where name like '%'||#{0}||'%'。
1 <select id="listCategoryByName" parameterType="string" resultType="Category"> 2 select * from category where name like concat('%',#{0},'%') 3 </select>
1 private void queryByName() throws IOException { 2 create(); 3 List<Category> categories = session.selectList("listCategoryByName", "i"); 4 for (Category category : categories) { 5 System.out.println(category.getName()); 6 } 7 close(); 8 }
2.多条件查询
结合前面的模糊查询,多一个限定id的条件。因为是多个参数,而selectList方法又只接受一个参数对象,所以需要把多个参数放在Map里,然后把这个Map对象作为参数传递进去。
1 private void queryByNameId() throws IOException { 2 create(); 3 Map<String, Object> params = new HashMap<String, Object>(); 4 params.put("id", 8); 5 params.put("name", "xiao"); 6 List<Category> categories = session.selectList("listCategoryByNameId", params); 7 for (Category category : categories) { 8 System.out.println(category.getName()); 9 } 10 close(); 11 }
1 <select id="listCategoryByNameId" parameterType="map" 2 resultType="Category"> 3 select * from category where id>#{id} and name like 4 concat('%',#{0},'%') 5 </select>
二、Mybatis的关系映射
1.一对多(一个分类对应多个产品)
<1>创建产品表以及产品表对应的实体。
1 package mybatis.pojo; 2 3 public class Product { 4 private int id; 5 private String name; 6 private float price; 7 8 public int getId() { 9 return id; 10 } 11 12 public void setId(int id) { 13 this.id = id; 14 } 15 16 public String getName() { 17 return name; 18 } 19 20 public void setName(String name) { 21 this.name = name; 22 } 23 24 public float getPrice() { 25 return price; 26 } 27 28 public void setPrice(float price) { 29 this.price = price; 30 } 31 32 public String toString() { 33 return "Product [id=" + id + ", name=" + name + ", price=" + price + "]"; 34 } 35 36 }
<2>修改Category实体类,提供product集合。
1 package mybatis.pojo; 2 3 import java.util.List; 4 5 public class Category { 6 private int id; 7 private String name; 8 private List<Product> products; 9 10 public int getId() { 11 return id; 12 } 13 14 public void setId(int id) { 15 this.id = id; 16 } 17 18 public String getName() { 19 return name; 20 } 21 22 public void setName(String name) { 23 this.name = name; 24 } 25 26 public List<Product> getProducts() { 27 return products; 28 } 29 30 public void setProducts(List<Product> products) { 31 this.products = products; 32 } 33 34 public String toString() { 35 return "Category [id=" + id + ", name=" + name + "]"; 36 } 37 }
<3>修改Category.xml
通过left join关联查询,对Category和Product表进行关联查询。与前面学习的有所区别,这里不是用的resultType, 而是resultMap,通过resultMap把数据取出来放在对应的对象属性里。
注: Category的id字段和Product的id字段同名,Mybatis不知道谁是谁的,所以需要通过取别名cid,pid来区分,name字段同理。
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6 <mapper namespace="mybatis.pojo"> 7 <resultMap type="Category" id="categoryBean"> 8 <id column="cid" property="id" /> 9 <result column="cname" property="name" /> 10 11 <!-- 一对多关系 --> 12 <!-- property:指定的是集合属性的值,ofType:指的是集合中元素的类型 --> 13 <collection property="products" ofType="Product"> 14 <id column="pid" property="id"></id> 15 <result column="pname" property="name" /> 16 <result column="price" property="price" /> 17 </collection> 18 </resultMap> 19 <!-- 关联查询分类和产品表 --> 20 <select id="listCategory" resultMap="categoryBean"> 21 select c.*, p.*, c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname' from 22 category c left join product p on c.id = p.cid 23 </select> 24 </mapper>
<4>测试
1 package mybatis.test; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.List; 6 7 import org.apache.ibatis.session.SqlSession; 8 import org.apache.ibatis.session.SqlSessionFactory; 9 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 10 11 import mybatis.pojo.Category; 12 import mybatis.pojo.Product; 13 14 public class testOneToMany { 15 16 public static void main(String[] args) throws IOException { 17 // TODO Auto-generated method stub 18 String resource = "mybatis-config.xml"; 19 InputStream inputStream = org.apache.ibatis.io.Resources.getResourceAsStream(resource); 20 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 21 SqlSession session = sqlSessionFactory.openSession(); 22 List<Category> categories = session.selectList("listCategory"); 23 for (Category c : categories) { 24 System.out.println(c); 25 List<Product> products = c.getProducts(); 26 for (Product product : products) { 27 System.out.println(" " + product.toString()); 28 } 29 } 30 session.commit(); 31 session.close(); 32 } 33 34 }
2.多对一(多个产品对应一个分类)
<1>修改Product.java,增加category属性
1 package mybatis.pojo; 2 3 import java.util.List; 4 5 public class Category { 6 private int id; 7 private String name; 8 private List<Product> products; 9 10 public int getId() { 11 return id; 12 } 13 14 public void setId(int id) { 15 this.id = id; 16 } 17 18 public String getName() { 19 return name; 20 } 21 22 public void setName(String name) { 23 this.name = name; 24 } 25 26 public List<Product> getProducts() { 27 return products; 28 } 29 30 public void setProducts(List<Product> products) { 31 this.products = products; 32 } 33 34 public String toString() { 35 return "Category [id=" + id + ", name=" + name + "]"; 36 } 37 }
<2>新增Product.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6 <mapper namespace="mybatis.pojo"> 7 8 9 <select id="getProduct" parameterType="int" resultType="Product"> 10 select * 11 from product where id= #{id} 12 </select> 13 14 <update id="updateProduct" parameterType="map"> 15 update product 16 set cid=#{cid} where id=#{pid} 17 </update> 18 19 <update id="updateProduct2" parameterType="Product"> 20 update product 21 set cid=#{category.id} where id=#{id} 22 </update> 23 24 <resultMap type="Product" id="productBean"> 25 <id column="pid" property="id" /> 26 <result column="pname" property="name" /> 27 <result column="price" property="price" /> 28 29 <!-- 多对一关系 --> 30 <!-- property:指定的是集合属性的值,ofType:指的是集合中元素的类型 --> 31 <association property="category" javaType="Category"> 32 <id column="cid" property="id" /> 33 <result column="cname" property="name" /> 34 </association> 35 </resultMap> 36 <!-- 关联查询分类和产品表 --> 37 <select id="listProduct" resultMap="productBean"> 38 select c.*, p.*, c.id 'cid', 39 p.id 'pid', c.name 'cname', p.name 'pname' from 40 category c left join 41 product p on c.id = p.cid 42 </select> 43 </mapper>
通过listProduct配置关联查询的sql语句。然后通过resultMap ,进行字段和属性的对应。使用association 进行多对一关系关联,指定表字段名称与对象属性名称的一一对应关系。
注: Category的id 字段 和Product的id字段同名,Mybatis不知道谁是谁的,所以需要通过取别名cid,pid来区分。name字段同理。
<3>在mybatis-config.xml中增加对于Product.xml的映射
1 <mapper resource="mybatis/pojo/Product.xml" />
<4>测试
1 package mybatis.test; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.List; 6 7 import org.apache.ibatis.session.SqlSession; 8 import org.apache.ibatis.session.SqlSessionFactory; 9 import org.apache.ibatis.session.SqlSessionFactoryBuilder; 10 11 import mybatis.pojo.Category; 12 import mybatis.pojo.Product; 13 14 public class testManyToOne { 15 16 public static void update() throws IOException { 17 String resource = "mybatis-config.xml"; 18 InputStream inputStream = org.apache.ibatis.io.Resources.getResourceAsStream(resource); 19 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 20 SqlSession session = sqlSessionFactory.openSession(); 21 22 Category category = session.selectOne("getCategory", 1); 23 Product product = session.selectOne("getProduct", 6); 24 product.setCategory(category); 25 session.update("updateProduct2", product); 26 27 // Map<String, Integer> params = new HashMap<String, Integer>(); 28 // params.put("cid", category.getId()); 29 // params.put("pid", product.getId()); 30 // 31 // session.update("updateProduct", params); 32 33 session.commit(); 34 session.close(); 35 } 36 37 public static void main(String[] args) throws IOException { 38 // TODO Auto-generated method stub 39 update(); 40 String resource = "mybatis-config.xml"; 41 InputStream inputStream = org.apache.ibatis.io.Resources.getResourceAsStream(resource); 42 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 43 SqlSession session = sqlSessionFactory.openSession(); 44 45 List<Product> products = session.selectList("listProduct"); 46 for (Product product : products) { 47 System.out.println(product + " 对应的分类是:" + product.getCategory()); 48 49 } 50 51 session.commit(); 52 session.close(); 53 54 } 55 56 }
练习:修改product(id=5)对应的类别为category(id=1)
两种解决思路
<1>首先查询id=5的product,再查询id=1的category,然后调用setCategory方法设置类别,然后对product进行更新操作。
<2>首先查询id=5的product,然后直接设置参数对product进行修改。
①先准备必要的sql语句。
Product.xml中
在updateProduct2中,因为product的成员变量中包含catergory对象,所以直接使用category.id获取类别的id。
1 <select id="getProduct" parameterType="int" resultType="Product"> 2 select * 3 from product where id= #{id} 4 </select> 5 6 <update id="updateProduct" parameterType="map"> 7 update product 8 set cid=#{cid} where id=#{pid} 9 </update> 10 11 <update id="updateProduct2" parameterType="Product"> 12 update product 13 set cid=#{category.id} where id=#{id} 14 </update>
Category.xml中
1 <select id="getCategory" parameterType="int" resultType="Category"> 2 select * 3 from category where id= #{id} 4 </select>
②测试
第一种思路
1 public static void update() throws IOException { 2 String resource = "mybatis-config.xml"; 3 InputStream inputStream = org.apache.ibatis.io.Resources.getResourceAsStream(resource); 4 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 5 SqlSession session = sqlSessionFactory.openSession(); 6 7 Category category = session.selectOne("getCategory", 1); 8 Product product = session.selectOne("getProduct", 6); 9 product.setCategory(category); 10 session.update("updateProduct2", product); 11 12 session.commit(); 13 session.close(); 14 }
第二种思路
1 public static void update() throws IOException { 2 String resource = "mybatis-config.xml"; 3 InputStream inputStream = org.apache.ibatis.io.Resources.getResourceAsStream(resource); 4 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 5 SqlSession session = sqlSessionFactory.openSession(); 6 7 Product product = session.selectOne("getProduct", 6); 8 Map<String, Integer> params = new HashMap<String, Integer>(); 9 params.put("cid", 1); 10 params.put("pid", product.getId()); 11 12 session.update("updateProduct", params); 13 session.commit(); 14 session.close(); 15 }
3.多对多(一张订单可以包含多种产品,一种产品可以出现在多张订单中)
为了维系多对多关系,必须要一个中间表。 在这里我们使用订单项(OrderItem)表来作为中间表。
<1>建立order表,order_item表
<2>添加数据
1 INSERT INTO order_ VALUES (1,'code000A'); 2 INSERT INTO order_ VALUES (2,'code000B'); 3 4 INSERT INTO order_item VALUES (null, 1, 1, 100); 5 INSERT INTO order_item VALUES (null, 1, 2, 100); 6 INSERT INTO order_item VALUES (null, 1, 3, 100); 7 INSERT INTO order_item VALUES (null, 2, 2, 100); 8 INSERT INTO order_item VALUES (null, 2, 3, 100); 9 INSERT INTO order_item VALUES (null, 2, 4, 100);
<3>添加实体类Order和OrderItem
①Order.java
1 package mybatis.pojo; 2 3 import java.util.List; 4 5 public class Order { 6 private int id; 7 private String code; 8 private List<OrderItem> orderItems; 9 10 public List<OrderItem> getOrderItems() { 11 return orderItems; 12 } 13 14 public void setOrderItems(List<OrderItem> orderItems) { 15 this.orderItems = orderItems; 16 } 17 18 public int getId() { 19 return id; 20 } 21 22 public void setId(int id) { 23 this.id = id; 24 } 25 26 public String getCode() { 27 return code; 28 } 29 30 public void setCode(String code) { 31 this.code = code; 32 } 33 34 }
②OrderItem.java
1 package mybatis.pojo; 2 3 public class OrderItem { 4 private int id; 5 private int number; 6 private Order order; 7 private Product product; 8 9 public int getId() { 10 return id; 11 } 12 13 public void setId(int id) { 14 this.id = id; 15 } 16 17 public int getNumber() { 18 return number; 19 } 20 21 public void setNumber(int number) { 22 this.number = number; 23 } 24 25 public Order getOrder() { 26 return order; 27 } 28 29 public void setOrder(Order order) { 30 this.order = order; 31 } 32 33 public Product getProduct() { 34 return product; 35 } 36 37 public void setProduct(Product product) { 38 this.product = product; 39 } 40 41 }
<4>映射文件
①Order.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6 <mapper namespace="mybatis.pojo"> 7 <resultMap type="Order" id="orderBean"> 8 <id column="oid" property="id" /> 9 <result column="code" property="code" /> 10 11 <collection property="orderItems" ofType="OrderItem"> 12 <id column="oiid" property="id" /> 13 <result column="number" property="number" /> 14 <association property="product" javaType="Product"> 15 <id column="pid" property="id" /> 16 <result column="pname" property="name" /> 17 <result column="price" property="price" /> 18 </association> 19 </collection> 20 </resultMap> 21 22 23 <select id="listOrder" resultMap="orderBean"> 24 select o.*,p.*,oi.*, o.id 25 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname' 26 from order_ o 27 left join 28 order_item oi on o.id =oi.oid 29 left join product p on p.id = oi.pid 30 </select> 31 <select id="getOrder" resultMap="orderBean"> 32 select o.*,p.*,oi.*, o.id 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname' 33 from order_ o 34 left join order_item oi on o.id =oi.oid 35 left join product p on p.id = oi.pid 36 where o.id = #{id} 37 </select> 38 </mapper>
②Product.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6 <mapper namespace="mybatis.pojo"> 7 8 <!-- 9 <select id="getProduct" parameterType="int" resultType="Product"> 10 select * 11 from product where id= #{id} 12 </select>--> 13 14 <update id="updateProduct" parameterType="map"> 15 update product 16 set 17 cid=#{cid} where id=#{pid} 18 </update> 19 20 <update id="updateProduct2" parameterType="Product"> 21 update product 22 set 23 cid=#{category.id} where id=#{id} 24 </update> 25 26 <resultMap type="Product" id="productBean"> 27 <id column="pid" property="id" /> 28 <result column="pname" property="name" /> 29 <result column="price" property="price" /> 30 31 <!-- 多对一关系 --> 32 <!-- property:指定的是集合属性的值,ofType:指的是集合中元素的类型 --> 33 <association property="category" javaType="Category"> 34 <id column="cid" property="id" /> 35 <result column="cname" property="name" /> 36 </association> 37 </resultMap> 38 <!-- 关联查询分类和产品表 --> 39 <select id="listProduct" resultMap="productBean"> 40 select c.*, p.*, c.id 'cid', 41 p.id 'pid', c.name 'cname', p.name 'pname' from 42 category c left join 43 product p on c.id = p.cid 44 </select> 45 <select id="getProduct" resultMap="productBean"> 46 select c.*, p.*, c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname' 47 from category c 48 left join product p on c.id = p.cid 49 where p.id = #{id} 50 </select> 51 </mapper>
③OrderItem.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE mapper 3 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 4 "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 5 6 <mapper namespace="mybatis.pojo"> 7 <insert id="addOrderItem" parameterType="OrderItem"> 8 insert into order_item 9 values(null,#{order.id},#{product.id},#{number}) 10 </insert> 11 <insert id="deleteOrderItem" parameterType="OrderItem"> 12 delete from order_item 13 where oid = #{order.id} and pid = #{product.id} 14 </insert> 15 </mapper>
<5>修改mybatis-config.xml
1 <mapper resource="mybatis/pojo/Order.xml" /> 2 <mapper resource="mybatis/pojo/OrderItem.xml" />
<6>查询操作
查询出所有的订单,然后遍历每个订单下的多条订单项,以及订单项对应的产品名称,价格,购买数量。通过Order.xml的listOrder对应的sql语句进行查询:
1 <select id="listOrder" resultMap="orderBean"> 2 select o.*,p.*,oi.*, o.id 3 'oid', p.id 'pid', oi.id 'oiid', p.name 'pname' 4 from order_ o 5 left join 6 order_item oi on o.id =oi.oid 7 left join product p on p.id = oi.pid 8 </select>
联合order_, order_item_, product_ 三张表进行查询
1 <resultMap type="Order" id="orderBean"> 2 <id column="oid" property="id" /> 3 <result column="code" property="code" /> 4 5 <collection property="orderItems" ofType="OrderItem"> 6 <id column="oiid" property="id" /> 7 <result column="number" property="number" /> 8 <association property="product" javaType="Product"> 9 <id column="pid" property="id" /> 10 <result column="pname" property="name" /> 11 <result column="price" property="price" /> 12 </association> 13 </collection> 14 </resultMap>
1 private static void listOrder(SqlSession session) { 2 List<Order> orders = session.selectList("listOrder"); 3 for (Order order : orders) { 4 System.out.println(order.getCode()); 5 List<OrderItem> orderItems = order.getOrderItems(); 6 for (OrderItem orderItem : orderItems) { 7 System.out.format(" %s %f %d ", orderItem.getProduct().getName(), orderItem.getProduct().getPrice(), 8 orderItem.getNumber()); 9 } 10 } 11 }
<7>建立关系
建立了让订单000A和产品z建立了关系。首先通过id分别获取Ordre对象和Product对象,然后创建一个新的OrderItem对象,接着设置Order,设置Product,设置数量,最后调用"addOrderItem" 对应的sql语句插入数据。
1 private static void addOrderItem(SqlSession session) { 2 Order order = session.selectOne("getOrder", 1); 3 Product product = session.selectOne("getProduct", 6); 4 OrderItem orderItem = new OrderItem(); 5 orderItem.setProduct(product); 6 orderItem.setOrder(order); 7 orderItem.setNumber(200); 8 9 session.insert("addOrderItem", orderItem); 10 }
addOrderItem调用insert into 语句插入一条OrderItem记录:
1 <insert id="addOrderItem" parameterType="OrderItem"> 2 insert into order_item 3 values(null,#{order.id},#{product.id},#{number}) 4 </insert>
<8>删除关系
删除了订单00A和产品z的关系,再次查询,就看不到产品z了。删除关系的时候,通过订单id(1)和产品id(6)进行删除。其实所谓的删除关系,就是删除掉OrderItem记录。
1 private static void deleteOrderItem(SqlSession session) { 2 Order order = session.selectOne("getOrder", 1); 3 Product product = session.selectOne("getProduct", 6); 4 OrderItem orderItem = new OrderItem(); 5 orderItem.setProduct(product); 6 orderItem.setOrder(order); 7 session.delete("deleteOrderItem", orderItem); 8 }
练习:删除订单A,那么就应该删除订单A在订单项里所对应的数据。
通过Mybatis执行多条sql语句需要增加一个参数:allowMultiQueries,多条语句之间用分号隔开。
1 <property name="url" value="jdbc:mysql://localhost:3306/test2?characterEncoding=UTF-8&allowMultiQueries=true" />
1 <delete id="deleteOrder" parameterType="Order"> 2 delete from 3 order_ where code = #{code}; 4 delete from 5 order_item 6 where oid = #{id} 7 </delete>
1 private static void deleteOrder(SqlSession session) { 2 Order order = session.selectOne("getOrder", 1); 3 session.delete("deleteOrder", order); 4 }