Mybatis笔记

Mybatis

MyBatis 是支持定制化 SQL、存储过程以及高级映射的持久层框架。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。

1.使用mysql数据库(MySQLWorkbench):
建库建表,填充数据。
这里写图片描述
这里写图片描述

2.创建实体类Category

public class Category {
	private int id;
	private String name;
	}

3.配置文件mybatis-config.xml(src目录下创建)
下面可以配置多个元素节点,而每个节点可以配置两个东西,一个是事务管理器配置,另一个是数据源配置。

<?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.bean" />
	</typeAliases>
	<!-- 设置别名,自动扫描com.bean下类型, 在Category.xml使用resultType时不用写全com.bean.Category,直接用Category -->
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" /><!-- 使用jdbc事务管理 -->
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url"
					value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8" />
					<!-- 数据库名,编码格式 -->
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
	</environments>
	<mappers>
		<mapper resource="com/bean/Category.xml" />
	</mappers><!-- 映射Category.xml -->


</configuration>

4.配置Category.xml(com.bean目录)

<?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.bean">
	<select id="listCategory" resultType="Category"><!-- 因为myBatis-config.xml直接写Category -->
		select * from category_
	</select>
</mapper>

5.测试类TestMybatis

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);
		// 通过配置文件"mybatis-config.xml"得到SQLSessionFactory(创建SqlSession对象的工厂)
		SqlSession session = sqlSessionFactory.openSession();
		// 通过SQLSessionFactory得到Session
		List<Category> cs = session.selectList("listCategory");
		// 通过session的selectList方法,调用sql语句listCategory。
		for (Category c : cs) {
			System.out.println(c.getName());
		}
	}
}

原理:
1. 应用程序找mybatis要数据
2. mybatis从数据库中请求数据

	 - 通过mybatis-config.xml 定位数据库
	 - 通过Category.xml执行对应的select语句
	 - 基于Catgory.xml把返回的数据库记录封装在Category对象中
	 - 把多个Category对象装在一个Category集合中
  1. 返回一个Category集合
    这里写图片描述
    基本的增删改查:
    实体类(映射数据库表)–>Mybatis-config.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="com.bean">
	<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"><!-- 因为myBatis-config.xml直接写Category -->
		select * from category_
	</select>
</mapper>

parameterType的用法:

1.基本数据类型,如输入参数只有一个,其数据类型可以是基本的数据类型,也可以是自己定的类类型。包括int,String,Integer,Date,如下:

(1)根据id进行相应的删除:

<delete id="deleteById" parameterType="Integer">

(2)添加员工:

<insert id="addEmp" parameterType="com.pojo.Employee">

2.复杂数据类型:包含java实体类,map。
另外MyBatis还提供了一个使用注解来参与多个参数的方式。这种方式需要在接口的参数上添加@Param注解此处要注意的是,由于该方法需要传入多个参数,在进行MyBatis配置时,没有办法同时配置多个参数,另外MyBatis还提供了一个使用注解来参数多个参数的方式。这种方式需要在接口的参数上添加@Param注解注意,以下两种写法是完全相同的。
但使用的时候要使用第一种类型
Userlogin(@Param(value =“name”)Stringname,
@Param(value =“password”)String password); //用户登录(String name,String password);
配置如下:

<select id =“login”resultType =“com.pojo.User”>
select * from us where name =#{name} and password =# {密码}
</ select>
<选择ID = “getWinLogByEventId”参数类型= “java.lang.Long中” >结果映射= “BaseResultMap”> > 选择<包括REFID = “基础_列_列表”/>从取胜_登录其中EVENTID =# { _ parameter,jdbcType = BIGINT} </ select >
3.获取参数中的值:
1.基本数据类型:#{参数}获取参数中的值 2.复杂数据类型:#{属性名}, map中则是#{key}
测试类:

 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);
		// 通过配置文件"mybatis-config.xml"得到SQLSessionFactory(创建SqlSession对象的工厂)
		SqlSession session = sqlSessionFactory.openSession();
		// 通过SQLSessionFactory得到Session
		Category c = new Category();
		// 增加
		c.setName("addCategory");
		session.insert("addCategory", c);
		// 删除
		c.setId(6);
		session.delete("deleteCategory", c);
		// 查询
		c = session.selectOne("getCategory", 3);
		System.out.println(c.getName());
		// 更改
		c = session.selectOne("getCategory", 4);
		c.setName("修改了姓名");
		session.update("updateCategory", c);

		// 遍历
		listAll(session);

		session.commit();
		session.close();

	}

	private static void listAll(SqlSession session) {
		// TODO Auto-generated method stub
		List<Category> cs = session.selectList("listCategory");
		// 通过session的selectList方法,调用sql语句listCategory。
		for (Category c : cs) {
			System.out.println(c.getName());
		}

	}

}

模糊查询:
实体类配置文件:

<select id="listCategoryByName" parameterType="String"
		resultType="Category">
		select * from category_ where name like concat('%',#{0},'%')
		<- 如果是oracle,写法是 - > 
		<-  select * from category_ where'name'like '%'||{0} ||'%' - > 
	</ select>

测试代码:

 List <Category> cs = session.selectList(“listCategoryByName”,“cat”); 
		for(Category c1:cs){ 
			System.out.println(c1.getName()); 
		} 

**多条件查询:**结合前面的模糊查询,多一个id多少的条件1。

<select id="listCategoryByIdAndName"  parameterType="map" resultType="Category">
    select * from   category_  where id> #{id}  and name like concat('%',#{name},'%')
</select>

因为是多个参数,而selectList方法又只接受一个参数对象,所以需要把多个参数放在Map里面,然后把这个Map对象作为参数传递进去

 Map <String,Object> params = new HashMap < >(); 
		params.put(“id”,0; 
		params.put(“name”,“cat”);
		List <Category> cs = session.selectList(“listCategoryByIdAndName”,params); 
		for(Category c1:cs){
		System.out.println(c1.getName());
		} 

1.一对多:(分类–产品)
1、数据库建表,填数据。
这里写图片描述
2、新建一个普通的一个pojo Product实体类

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() {
		// TODO Auto-generated method stub
		return "Product [id=" + id + ",name=" + name + ",price=" + price;
	}
}

3.修改Category实体类

在Category类中增加:
List<Product> products;

	public List<Product> getProducts() {
		return products;
	}

	public void setProducts(List<Product> products) {
		this.products = products;
	}

4.修改Category.xml
通过left join关联查询,对Category和Product表进行关联查询。
与前面学习的有所区别,这里不是用的resultType, 而是resultMap,通过resultMap把数据取出来放在对应的 对象属性里
注: Category的id 字段 和Product的id字段同名,Mybatis不知道谁是谁的,所以需要通过取别名cid,pid来区分。
name字段同理。

<mapper namespace="com.bean">
<resultMap type="Category" id="categoryBean"> <id column="cid" property="id" 
		/> <result column="cname" property="name" />
	<!-- 一对多关系 -->
	<!-- property:指集合属性的值,ofType:指集合中元素的类型 -->
<collection property="products" ofType="Product"> 
<id column="pid" property="id" />
		 <result column="pname" property="name" />
		 <result column="price" property="price" />
		 </collection>
		 </resultMap>
	<!-- left join关联查询 产品分类和产品表 -->
<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>

5、测试

// 一对多关系
	public static void listCategory(SqlSession session) {
		List<Category> cs = session.selectList("listCategory");
		for (Category category : cs) {
			System.out.println(category);
			List<Product> ps = category.getProducts();
			for (Product product : ps) {
				System.out.println("/t" + product);
			}
		}

	}

2.多对一关系(产品–>分类)
1.修改实体类为Product增加category属性

private Category category;
	public Category getCategory() {
		return category;
	}
	public void setCategory(Category category) {
		this.category = category;
	}

2.新建Product.xml
提供Product.xml,通过listProduct配置关联查询的sql语句。
然后通过resultMap ,进行字段和属性的对应。
使用association(关联) 进行多对一关系关联,指定表字段名称与对象属性名称的一一对应关系
注: Category的id 字段 和Product的id字段同名,Mybatis不知道谁是谁的,所以需要通过取别名cid,pid来区分。
name字段同理。

<?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.bean">
	<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>

3.在mybatis-config.xml中增加对于Product.xml的映射

<mapper resource="com/bean/Product.xml" />

4.测试

// 多对一关系
	public static void listProduct(SqlSession session) {
		List<Product> ps = session.selectList("listProduct");
		for (Product product : ps) {
			System.out.println(product + "\t对应的分类是\t" + product.getCategory());
		}
	}

3.多对多关系
以订单Order和产品Product为例:
一张订单***里可以包含***多种产品
一种产品 可以出现在***多张订单***里
这就是多对多关系,为了维系多对多关系,必须要一个中间表。 在这里我们使用订单项(OrderItem)表来作为中间表。

  1. 查询多对多关系
  2. 建立多对多关系
  3. 删除多对多关系

1.数据库建表填充数据。
这里写图片描述新建order_表,同理新建order_item_表
填充数据:
这里写图片描述

2.新建实体类Order和OrderItem
自动生成getset方法。

public class Order {
	private int id;
	private String code;
	
	List<OrderItem> orderItems;
}
public class OrderItem {
	private int id;
	private int number;
	private Order order;
	private Product product;
}

3.配置映射文件Product、Order、OrderItem。
Product.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="com.bean">
	<resultMap type="Product" id="productBean">
		<id column="pid" property="id" />
		<result column="pname" property="name" />
		<result column="price" property="price" />
		<!-- 多对一的关系 -->
		<!-- property: 指的是属性名称, javaType:指的是属性的类型 -->
		<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>

Order.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="com.bean">
	<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>

OrderItem.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="com.bean">
	<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
增加映射文件

<mapper resource="com/bean/Order.xml" />
<mapper resource="com/bean/OrderItem.xml" />

4.建立关系
(1).查询

Test

	private static void listOrder(SqlSession session) {
		List<Order> orders = session.selectList("listOrder");
		for (Order order : orders) {
			System.out.println(order.getCode());
			List<OrderItem> oItems = order.getOrderItems();
			for (OrderItem orderItem : oItems) {
				System.out.format("\t%s\t%f\t%d%n", orderItem.getProduct().getName(), orderItem.getProduct().getPrice(),
						orderItem.getNumber());
			}
		}
	}

(2).增加关系

// 建立关系(插入数据)
	// 首先通过id分别获取Order和Product对象,接着就新建一个OrderItem对象,set order和product
	// 还有数量,最后用"addOrderItem"对应的sql语句插入.
	private static void addOrderItem(SqlSession session) {
		Order order = session.selectOne("getOrder", 1);
		Product product = session.selectOne("getProduct", 2);
		OrderItem orderItem = new OrderItem();
		orderItem.setProduct(product);
		orderItem.setOrder(order);
		orderItem.setNumber(200);
		session.insert("addOrderItem", orderItem);
	}

(3).删除关系

// 删除关系(就是删掉OrderItem记录)
	// 同上通过对应的Order和Product的id进行删除
	private static void deleteOrderItem(SqlSession session) {
		Order order = session.selectOne("getOrder", 1);
		Product product = session.selectOne("getProduct", 2);
		OrderItem orderItem = new OrderItem();
		orderItem.setProduct(product);
		orderItem.setOrder(order);
		session.delete("deleteOrderItem", orderItem);

	}

(4).修改
多对多不存在修改关系的做法,就是删除旧的,然后新增一条即达到修改的效果。

动态sql------if标签
以查询Product表为例:
1.Product.xml配置文件
使用模糊查询的时候可能会用到不同的字段,如果查询一次使用一条sql语句,会变得难以维护,就能使用Mybatis的动态sql----if标签
;如果没有传入参数那么就是查询所有,这样就可以一条语句应付多种情况。

<mapper namespace="com.bean">
	<select id="listProductByName" resultType="Product">
		select * from product_
		<if test="name!=null">
			where name like concat('%',#{name},'%')
		</if>
	</select>
</mapper>

2.test

	// 查询Product使用模糊查询
	private static void listProductByName(SqlSession session) {
		Map<String, Object> params = new HashMap<>();
		params.put("name", "b");//"b"通过动态输入灵活查询
		List<Product> ps = session.selectList("listProductByName", params);
		for (Product product : ps) {
			System.out.println(product);
		}

	}

动态sql------where标签
1.修改Product.xml配置文件
当出现多条件查询的时候不能愉快的直接使用
select * from product_ where name like concat(’%’,#{name},’%’) and price > #{price}会出现name为空price不为空的语句错误;这时候就使用where标签。
如果任何条件都不成立,那么就在sql语句里就不会出现where关键字
如果有任何条件成立,会自动去掉多出来的 and 或者 or。

<select id="listProductByName" resultType="Product">
		select * from product_
		<where>
			<if test="name!=null">
				and name like concat('%',#{name},'%')
			</if>
			<if test="price!=null and price!=0">
				and price > #{price}
			</if>
		</where>
	</select>

2.test

// 多条件查询
	private static void listProductByNameAndPrice(SqlSession session) {
		Map<String, Object> params = new HashMap<>();
		params.put("name", "b");// 这时params值为不为空都可以正常运行
		params.put("price", "2");
		List<Product> ps = session.selectList("listProductByName", params);
		for (Product product : ps) {
			System.out.println(product);
		}
	}

动态sql------set标签
1.修改Product.xml配置文件
与where标签类似的,在update语句里也会碰到多个字段相关的问题。 在这种情况下,就可以使用set标签:

<update id="updateProduct" parameterType="Product">
		update product_
		<set>
			<if test="name!=null">name=#{name},</if>
			<if test="price!=null">price=#{price}</if>
		</set>
		where id=#{id}
	</update>

2.test

// 修改Product
	private static void updateProductById(SqlSession session) {
		Product p=new Product(5,"product zz",9.99f);
		session.update("updateProduct", p);
	}

动态sql------trim标签
trim 用来定制想要的功能,比如where标签就可以用

<trim prefix="WHERE" prefixOverrides="AND|OR">
</trim>

替换
set标签就可以用

<trim prefix="SET" suffixOverrides=",">
</trim>

替换。

<select id="listProductByName" resultType="Product">
		select * from product_
		<trim prefix="WHERE" prefixOverrides="AND|OR"><!-- =where -->
			<if test="name!=null">
				and name like concat('%',#{name},'%')
			</if>
			<if test="price!=null and price!=0">
				and price > #{price}
			</if>
		</trim>
	</select>
	<update id="updateProduct" parameterType="Product">
		update product_
		<trim prefix="SET" suffixOverrides=","><!-- set -->
			<if test="name!=null">name=#{name},</if>
			<if test="price!=null">price=#{price}</if>
		</trim>
		where id=#{id}
	</update>

效果和where和set一样。

动态sql------choose标签
1.修改Product.xml配置文件

<!-- Mybatis里面没有else标签,但是可以使用when otherwise标签来达到这样的效果。 -->
	<select id="productList" resultType="Product">
		select * from product_
		<where>
			<choose>
				<when test="name!=null">and name like concat('%',#{name},'%')</when>
				<when test="price!=null and price!=0">and price > #{price}</when>
				<otherwise>
					and id>1
				</otherwise>
				<!-- 起作用是: 提供了任何条件,就进行条件查询,否则就使用id>1这个条件。 -->
			</choose>
		</where>
	</select>

2.test

private static void productList(SqlSession session) {
		Map<String, Object> params = new HashMap<>();
		List<Product> ps = session.selectList("productList", params);
		for (Product product : ps) {
			System.out.println(product);
		}
	}

动态sql------foreach标签
1.修改Product.xml配置文件

	<!-- foreach标签通常用于in 这样的语法里,比如查询id是1,2,3的数据 -->
	<select id="listProductForeach" resultType="Product">
		SELECT * FROM product_
		WHERE ID in
		<foreach item="item" index="index" collection="list" open="("
			separator="," close=")">
			#{item}
		</foreach>
	</select>

2.test

private static void productListForeach(SqlSession session) {
		List<Integer> ids = new ArrayList<>();
		ids.add(1);
		ids.add(2);
		ids.add(3);
		List<Product> ps = session.selectList("listProductForeach", ids);
		for (Product product : ps) {
			System.out.println(product);
		}
	}

动态sql------bind标签
1.修改Product.xml配置文件

<!-- bind标签就像是再做一次字符串拼接,方便后续使用 -->
	<!-- 如下,在模糊查询的基础上,把模糊查询改为bind标签。 -->
	<select id="listProductBind" resultType="Product">
		<bind name="likename" value="'%'+name+'%'" />
		select * from product_ where name like #{likename}
	</select>

2.test

private static void listProductBind(SqlSession session) {
		Map<String, String> params = new HashMap<>();
		params.put("name", "product");
		List<Product> ps = session.selectList("listProductBind", params);
		for (Product product : ps) {
			System.out.println(product);
		}
	}
posted @ 2018-03-01 16:19  小沐酱  阅读(2)  评论(0编辑  收藏  举报  来源