狂神说Java-Mybatis笔记

1.环境搭建

1.创建一个干净的maven项目,删除src目录,新建模块,导入依赖
2.在resource目录下编写mybatis-config.xml文件,连接数据库

//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>
    <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/jdbcStudy?userSSL=true&useUnicode=true&characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

<!--    每一个Mapper.xml文件都需要在此处被注册-->
    <mappers>
        <mapper resource="com/lewis/dao/ShopMapper.xml" />
    </mappers>
</configuration>

3.新建dao,pojo,utils目录,在utils目录下建立MybatisUtils工具类,获取mybatis-config.xml资源,建立sqlSessionFactory工厂对象,并用openSession方法建立sqlSession对象

//MybatisUtils.java
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            //使用MyBatis第一步,获取SqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //调用sqlSessionFactory对象的openSession方法获取sqlSession对象,使用sqlSession对象操作数据库
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession();
    }

4.在pojo目录下编写实体类,与数据表建立ORM映射

5.在dao目录下建立表名Mapper接口,指定对这张表的操作声明,如声明getList方法
6.在dao目录下建立表名Mapper.xml文件,实现sql操作。其中mapper标签中的namespace的值为接口位置,指定要操作的表;select标签中的id值为要实现的接口中的方法,resultType值为表名对应的pojo实体类
7.在mybatis-config.xml文件中注册Mapper
8.注意在pom.xml文件中建立build标签,使java目录下的xml文件能够生效
9.在test目录下编写测试文件测试。

2.增删改查(重点)

在配置好之后,CURD只需要在dao层下的的Mapper接口类里面加方法,在Mapper.xml文件里加标签,在测试类里加方法即可。

//ShopMapper.java
public interface ShopMapper {
    //得到商品列表
    List<Shop> getShopList();
    //根据id查询
    Shop getShopById(int i);
    //增
    int addShop(Shop shop);
    //改
    int updateShop(Shop shop);
    //删
    int deleteShop(int id);
}
//ShopMapper.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">
<!--绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.lewis.dao.ShopMapper">
<!--获得整个列表-->
    <select id="getShopList" resultType="com.lewis.pojo.Shop">
        select * from jdbcstudy.shop;
    </select>
<!--根据id查询-->
    <select id="getShopById" resultType="com.lewis.pojo.Shop" parameterType="int">
        select * from jdbcstudy.shop where id=#{id};
    </select>
<!--插入-->
    <insert id="addShop" parameterType="com.lewis.pojo.Shop">
        insert into jdbcstudy.shop values (#{id},#{name},#{money});
    </insert>
<!--更新-->
    <update id="updateShop" parameterType="com.lewis.pojo.Shop">
        update jdbcstudy.shop set name = #{name},money = #{money} where id=#{id};
    </update>
<!--    删除-->
    <delete id="deleteShop" parameterType="int">
        delete from jdbcstudy.shop where id = #{id};
    </delete>
</mapper>
//ShopDaoTest.java
public class ShopDaoTest {
    public static void selectList(){
        //第一步,获得sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //第二步,执行sql,getMapper
        ShopMapper shopDao = sqlSession.getMapper(ShopMapper.class);
        List<Shop> shopList = shopDao.getShopList();
        //展示查询结果
        for (Shop shop : shopList) {
            System.out.println(shop);
        }
        //第三步,关闭sqlSession
        sqlSession.close();
    }
    //根据id查
     public static void getListById(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        ShopMapper mapper = sqlSession.getMapper(ShopMapper.class);
        Shop shopById = mapper.getShopById(1);
        System.out.println(shopById);
        sqlSession.close();
    }
    //
    public static  void addShop(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        ShopMapper mapper = sqlSession.getMapper(ShopMapper.class);
        
        int res = mapper.addShop(new Shop(3,"liwen",1000));//增删改只有这一句不同
		//mapper.updateShop(new Shop(3,"liwen",2000)); 更新
		//mapper.deleteShop(3);删除
		
        if(res>0)
            sqlSession.commit();//增删改操作需提交事务。
        sqlSession.close();
    }
    

3.配置文件mybatis-config.xml(重点)

3.1 db.properties

resources目录下新建db.properties,里面放数据库连接信息。

//db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcStudy?userSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
password=123456

然后在mybatis-config.xml里面可以使用properties标签引入,使用${name}使用

//mybatis-config.xml
<properties resource="db.properties">
        <property name="password" value="123456"/>
</properties>
<environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

3.2 设置别名

//mybaits-config.xml
<typeAliases>
 	    <typeAlias type="com.lewis.pojo.Shop" alias="Shop" />//直接给实体类起别名
        <package name="com.lewis.pojo"/>
</typeAliases>

在这个包下的所有实体类,别名默认为这个类的类名首字母小写,但也可以使用注解改。适用于包下实体类比较多的情况

3.3 映射器mapper

每一个Mapper.xml文件都需要在此处被注册

//mybatis-config.xml
<mappers>
        <mapper resource="com/lewis/dao/ShopMapper.xml"/>
        <mapper class="com.lewis.dao.ShopMapper"/>//推荐使用class方式注册
</mappers>
  • 接口和他的Mapper配置文件必须同名!
  • 接口和他的Mapper配置文件必须在同一包下!
sqlSessionFactoryBuilder ,sqlSessionFactory, sqlSession, mapper关系

1.sqlSessionFactoryBuilder:这个类可以被实例化和丢弃,一旦创建了sqlSessionFactory,就不在需要它了。
2.sqlSessionFactory:一旦被创建在整个程序的运行期间都存在,可以想象为一个数据库连接池,有且只能有一个,可用单例模式来实现。
3.sqlSession:可以想象为一个数据库连接池中的一个连接,不是线程安全的,因此不能被共享,最佳作用域是放在方法被,用完之后需手动关闭,否则会占用资源。
4.mapper:相当于一个具体的业务,执行增删改查

4.结果集映射

简单的语句不需要结果集映射,复杂语句只需描述他们之间的关系即可

//ShopMapper.xml
<resultMap id="ShopMap" type="Shop">
    <result column="id" property="shopId"/>//前者是数据表字段,后者是实体类属性,建立映射
    <result column="name" property="username"/>
    <result column="pwd" property="password"/>
    <association property="..."/>//一对多,多对一关系
    <collection property="..."/>
</resultMap>

5.日志工厂

1 STDOUT_LOGIN(标准日志输出):在mybatis-config.xml中设置,可以直接使用

<settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

2 log4j
导入包,新增依赖

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
</dependency>

在mybatis-config.xml设置,值为LOG4J

在resources目录下新建log4j.properties文件,百度log4j配置,复制粘贴
在要使用日志输出的类中,导入log4j包;获取日志对象,参数为当前类名

6.分页

sql 语句分页:select * from tableName limit startIndex,pageSize
mybatis分页:
1.接口 List getUserByLimit(Map map);
2.Mapper.xml: select * from mybatis.user limit #{startIndex},#{pageSize}
3.测试:

HashMap<String,Integer> map = new HashMap<String,Integer>();
map.put("startIndex",0);
map.put("pageSize",2);
List<User> userList = mapper.getUserByLimit(map);

7.注解开发

注解适合比较简单的sql语句,复杂的业务还是要用Mapper.xml文件完成语句执行

7.1 用注解实现增删改查

@Select("select * from user")
List<User> getUsers();
@Update("update user set name=#{},password=#{} where id=#{}")
int updateUser(User user);
@Insert("insert into user(id,name,password) values(#{id},#{name},#{password})")
int addUser(User user);
@Delete("delte from user where id=#{}")
int deleteUser(@Param(id)int id);

关于@Param()

  • 基本类型的参数或String类型的参数,需要加上,引用类型不需要加
  • 如果只有基本类型参数,可以不加,但建议加
  • 我们在SQL中引用的就是@Param中设定的属性名

然后在mybatis-config.xml中注册

7.2 Lombok插件

在实体类上加注解,可以不用写get/set,toString,有参、无参构造等方法
1.在IDEA中安装插件
2.导入jar包(依赖)
3.在实体类上加注解
缺点:对新手不友好,降低代码可阅读性,其他的项目也必须安装这个插件才能运行

8.多对一,一对多

8.1 多对一:多个学生对应同一个老师

有两张表,student表有id,name,tid字段;teacher表有id,name字段,tid为外键

//接口类
List<Student> getStudent();
//实体类
private int id;
private String name;
Private Teacher teacher;
//Mapper.xml
//方法一:按照结果嵌套,推荐使用
<select id="getStudent" resultMap="StudentTeacher">
	select s.id sid,s.name sname,t.name tname
	from student s,teacher t
	where s.id=t.id
</select>
<resultMap id="StudentTeacher" type="Student>
	<result property="id" column="sid"/>//property表示属性;colnum表示数据库字段,别名优先
	<result property="name" column="sname"/>
	<association property="teacher" javaType="Teacher">//对象用association,嵌套
		<result property="name" column="tname"/>
	</association>
</resultMap>
//方法二:子查询:查询所有的学生信息,根据查询出来的学生的tid,寻找对应的老师信息
<select id="getStudent" resultMap="StudentTeacher">//返回结果为一个Map
	select * from student;
</select>
<resultMap id="StudentTeacher" resultType="Student">//返回结果为一个Student对象
	<result property="id" column="id"/>
	<result property="name" column="name"/>
	<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<select id="getTeacher" resultType="Teacher">//返回结果为一个Teacher对象
	select * from teacher where id=#{id}
</select>
  • 如果返回结果为一个对象,用association标签展开;如果返回结果为一个集合,用collection标签展开
  • 集合中的泛型信息,使用ofType获取

8.2 一对多:一个老师对应多个不同的学生

//接口类
List<Teacher> getTeacher();
//实体类
private int id;
private String name;
private List<Student> student;
<select id="getStudent" resultMap="StudentTeacher">
	select s.id sid,s.name sname,t.name tname,t.id tname
	from student s,teacher t
	where s.id=t.id and tid=#{tid}
</select>
<resultMap id="TeacherStudent" type="Teacher">
	<result property="id" column="tid"/>//property表示属性;colnum表示数据库字段,别名优先
	<result property="name" column="tname"/>
	<collection property="students" ofType="Student">//集合中的泛型信息,使用ofType获取
		<result property="id" column="sid"/>
		<result property="name" column="sname"/>
		<result property="tid" column="tid"/>
	</collection >
</resultMap>

9.动态SQL

根据不同条件生成不同的SQL语句,本质是在SQL层面去执行一些逻辑代码

9.1 if 标签

不输入条件,查询所有;输入参数条件,将满足条件的if标签下的sql语句追加到初始sql语句末尾

<select id="queryBolgIF" parameterType="map" resultType="blog">
	select * from mybatis.blog where 1=1
	<if test="title! = null">
		title = #{title}
	</if> 
	<if test="author! = null">
		and author= #{author}
	</if> 
</select>

9.2 where 标签

将上面的where 1=1 换成了where标签。有if取值为真,才会去插where子句,且若语句的开头为OR或AND,会将其自动去除

<select id="queryBolgIF" parameterType="map" resultType="blog">
	select * from mybatis.blog 
	<where>
		<if test="title! = null">
			title = #{title}
		</if> 
		<if test="author! = null">
			and author= #{author}
		</if> 
	</where>
</select>

9.3 choose-when-otherwise

choose标签里面选择一个执行,优先级与顺序有关,类似于 if-if-else语句

<select id="queryBolgIF" parameterType="map" resultType="blog">
	select * from mybatis.blog 
	<where>
		<choose>
			<when test="title!=null">
				title = #{title}
			</when>
			<when test="author!=null">
				and author= #{author}
			</when>
			<otherwise>
				and views = #{views}
			</otherwise>
		</choose>
	</where>
</select>

9.4 update-set-if

注意在if标签里加逗号,如果有多余的逗号,标签会自动删除

<update id="queryBolgUpdate" parameterType="map">
	update mybatis.blog
	<set>
		<if test="title! = null">
			title = #{title},//注意加逗号
		</if> 
		<if test="author! = null">
			and author= #{author}
		</if> 
	</set>
	where id = #{id}
</update>

9.5 sql片段

使用 sql标签抽取一些公共信息,然后使用include标签引用即可。
注意:1.最好基于单表来定义片段;2.不要存在where标签,因为会自动去除一些东西

//抽取
<sql id = "A">
	公共部分
</sql>
//引用
<include refid="A"/>

9.6 foreach

open的值代表开头,close的值e代表结尾,separato的值r代表用来分隔的符号,一般为,,or这些。
需求:查询id值为1,2,3的用户信息

<select id="queryBolgForeach" parameterType="map" resultType="blog">
	select * from mybatis.blog
	<where>
		<foreach collection="ids" item="id"	open="and(" close=")" separator="or">
			id = #{id}
		</foreach>
	</where>
</select>

拼接后的sql语句为:select * from mybatis.blog where 1=1 and (id=1 or id=2 or id=3)

10.缓存

一级缓存

Mybatis默认开启,只在一次sqlSession中有效,也就是拿到连接到关闭连接这个区间。增删改操作会改变数据,会使缓存失效。

二级缓存

Mybatis默认关闭,需要手动开启,一个命名空间对应一个二级缓存。

  • 只要开启了二级缓存,在同一个Mapper下都有效
  • 所有的数据都会先放在一级缓存中,只有当会话提交或关闭时,才会提交到二级缓存
  • 第一次进来时,先查二级缓存,再查一级缓存,最后查数据库

开启二级缓存:在Mapper.xml文件中加入即可

你可能感兴趣的:(Java)