之前访问数据库都是除了自己写sql语句,还要statement,connection等等比较繁琐的的重复代码。
mybatis的作用就是它帮我们去做这些繁琐的事情,我们只需要自己提供sql语句就行了。
配置
先把数据库和数据表创建好。
创建的表名为category_,
然后创建对应的pojo:
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,这是mybatis的主配置文件,在这里面提供 连接数据库的各种信息,还有包的别名、映射的xml。
<typeAliases>中就是包的别名
<environments>里面是数据库基本信息的配置
<mappers>就是对应的类的映射。
<?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>
然后我们对Cagegory.xml进行配置:
namespace是命名空间 ,然后里面的select就是写sql语句的地方了,要注意的是id是唯一的,也是我们在使用的时候调用这个sql语句的依据,然后resultType就是规定返回类型,差不多和java方法里面的返回值类型。
<?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>
然后咱写个测试这个sql语句功能的类:
main主函数里面:
第一句:因为我们在mybatis-config.xml中写好了数据库的配置信息,还有映射等信息,这里就是定位是哪一个数据库。
第二句:把配置信息转换成输入流
第三局:通过配置信息得到sqlsessionfactory
第四局:通过sqlsessionfactory得到session
然后还记得之前配置的category.xml中的映射吗?完成上面四句话之后,就可以通过session,凭借我们写的唯一id,来调用里面的各种sql语句啦。
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());
}
}
}
CRUD
.好吧,又是繁琐的CRUD
什么?这次不再繁琐了,因为我们只需要在刚才的category.xml中写上增删改查的sql就行了。是真滴舒服。
有不同的地方是,有些功能会用到参数,第一是需要加上 parameterType属性,里面就是参数类型了。(有个特殊的是_int,为什么有下划线呢,是因为_int对应的是int ,而直接int对应的是integer,这是mybatis系统自带的别名。)参数是用#{xx}的形式表示的。
<?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>
测试一下add:
和之前只需要list不一样,多上了session.commit(),和session.close()。
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());
}
}
}
模糊查询
就像咱正常的搜索一样,不可能完全匹配,所以就有模糊查询这一功能,就像正则表达式一样。
concat里面的%就是通配符了,表示我穿过来的字符串前面和后边都可以有多余的东西,仍能匹配。
#{0}就是指咱传过来的string了,0是指第一个参数的意思吧。
<?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="listCategoryByName" parameterType="string" resultType="Category">
select * from category_ where name like concat('%',#{0},'%')
</select>
</mapper>
多条件查询
比如在上面模糊查询的基础上再加上一个条件参数,咱要找不仅是名字带有string的,而且id>5,那这就涉及到有两个参数的问题了,这要怎么传呢?
因为是多个参数,而selectList方法又只接受一个参数对象,所以需要把多个参数放在Map里,然后把这个Map对象作为参数传递进去。
映射部分:
<select id="listCategoryByIdAndName" parameterType="map" resultType="Category">
select * from category_ where id> #{id} and name like concat('%',#{name},'%')
</select>
测试代码:
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());
}
一对多关系
这里我仔细品了好久才品懂了一点。写详细点,以后复习好看。
首先新增一个product_表,有id、name、cid、price
准备一个Product pojo 有id、name、price
给category pojo加上product的集合。
然后就是关键了,因为一共category可能会对应很多product嘛,所以这里,一对多的映射,它lei了!
首先看下面的select部分,发现有个resultMap属性,这是啥? 之前不是resultType吗,咋变了
一查才发现,resultMap也是规定返回类型的,但是能它比resultType更高级一点,也需要自己去实现这个类型。
那么我们目光向上就可以看到有一个resultMap标签,它的id和下面select一样,那就是这里了。
type是类型,下面第一条id 是主键,其他不是主键的属性就用result来写了。 column表示在数据库列的名称,我理解为别名(后边告诉你别名是啥),property就是对应的属性了。
重点在collection标签,就是它,它就表示一对多,你看它里面就是咱的那个“多” products。
还有疑惑的地方就是下面select里面的sql语句, left join表示关联查询,就是在查的时候不止用到一个表中的属性。on后边就是条件。
那么前面那么长一段:
c.*, p.*, c.id 'cid', p.id 'pid', c.name 'cname', p.name 'pname'
是啥? 没错,由于咱各种表之中很可能会有重复的名字,比如category里面有id,product里面也有id,这里包括我们resultMap中的column中就是在进行别名处理。
<?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="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>
<!-- 关联查询分类和产品表 -->
<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>
多对一关系
首先咱在product pojo里面加上一个category属性,表示这个product的归属那个分类。然后就通过product.xml来展现这个 多对一的关系啦:
说实话,和之前一对多的关系挺像,唯一不同的是 collection变成了association了,没错! association就是表示多对一关系。其他部分和上面类似,不赘述啦。
<?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" />
<!-- 多对一的关系 -->
<!-- property: 指的是属性名称, javaType:指的是属性的类型 -->
<association property="category" javaType="Category">
<id column="cid" property="id"/>
<result column="cname" property="name"/>
</association>
</resultMap>
<!-- 根据id查询Product, 关联将Orders查询出来 -->
<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>
多对多关系!
是在上面两种关系的衍生,但是实战很少用,就看看xml的写法吧,新加了两个表 order和orderitem。
在一对多的关系里面套了一层多对一,通过用于连接的oid pid来处理。
<?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>