mybatis学习笔记——持续更新——附b站视频网址

mybatis主要类介绍



1、SqlSession(核心方法)


SqlSession接口:定义了操作数据的方法,例如:selectOne(),selectList(),insert(),update(),delete(),commit(),rollback()


在这里插入图片描述

使用要求:SqlSession对象线程不安全,需要在方法内使用,在执行sql语句之前,使用openSession()获取sqlSession对象。在执行完sql语句后,需要关闭它,执行SqlSession.close(),这样保证他的使用是线程安全的


2、SqlSessionFactoryBuilder: 创建SqlSessionFactory对象

SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);

3、SqlSessionFactory

重量级对象,程序创建一个对象耗时比较长,使用资源比较多,在整个项目一个就够了
SqlSessionFactory是个接口,实现类是defaultSqlSessionFactory。作用是获取sqlSession对象。

openSession()方法说明:

openSession():	无参,获取是非自动提交事务的sqlSession对象

openSession(boolean);	openSession(true)获取自动提交事务的Sqlsession
    
SqlSession sqlSession = factory.openSession();

4、Resources:

mybatis中负责读取主配置文件

String config = "mybatis.xml";
InputStream in = Resources.getResourceAsStream(config);



模板文件介绍


dao映射文件

mybatis-mapper模板,设置–>代码模板中添加mybatis-mapper.xml模板,下次写dao映射文件直接改这个模板就行

<?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="dao接口的全限定名称">
    
    //查询
    <select id="接口中方法名" resultType="结果类型,类的全限定名称">
        //sql语句
    </select>
    
    //插入
    <insert id="....">
    </insert>
    
    //更新
    <update id="...." >
    </update>
    
    //删除
    <delete id="...">
    </delete>

</mapper>

如下图,创建mybatis-mapper.xml模板
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JJCcIof3-1605765434073)(C:\Users\张衡\AppData\Roaming\Typora\typora-user-images\image-20201119102147133.png)]


设置好模板,下次新建就有 mybatis-mapper 可以选择,如下图
在这里插入图片描述


主配置文件 mybatis.xml


同理,创建mybatis-config模板,下次创建主配置文件mybatis.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>
    <settings>
        <!--mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <environments default="和某个environmentid值一致,表示连接哪个数据库">
        
        <environment id="">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/"/>
                <property name="username" value="root"/>
                <property name="password" value="137171"/>
            </dataSource>
        </environment>
  
    </environments>

    <!--sql映射:指定一个dao接口的映射文件位置-->
    <mappers>
        <mapper resource="映射文件的类路径位置"/>
        <!--<mapper resource="com/zh/dao/Student01Dao.xml"/>-->
    </mappers>
</configuration>

映射文件的类路径位置,如下图
在这里插入图片描述



动态代理


mybatis帮你创建dao接口的实现类,在实现类中调用SqlSession的方法执行sql语句


使用动态代理方式

1.获取SqlSession对象,SqlSessionFactory.openSession()
2.使用getMapper方法获取某个接口的对象,sqlSession.getMapper(接口.class)
3.使用dao接口的方法,调用方法就执行了mapper文件中的sql语句

使用动态代理的要求

1.dao接口和mapper文件放在一起,同一个目录
2.dao接口和mapper文件名称一致
3.mapper文件中的namespace的值是dao接口的全限定名称
4.mapper文件中的<select>,<insert>,<update>,<delete>等的id是接口中方法名称
5.dao接口中不要使用重载方法,不要使用同名的,不同参数的方法

MyBatisUtils.java 用于获取 sqlSession对象

public class MyBatisUtils {
    private static SqlSessionFactory factory = null;
    static {
        String config="mybatis.xml";
        try {
            InputStream in = Resources.getResourceAsStream(config);
            //使用SqlSessionFactoryBuilder,创建SqlSessionFactory对象
            factory = new SqlSessionFactoryBuilder().build(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取SqlSession的方法
    public static SqlSession getSqlSession(){
        SqlSession sqlSession = null;
        if (factory != null){
            sqlSession = factory.openSession();//非自动提交事务
        }
        return sqlSession;
    }
}

1、自己创建实现类的方式(原始方式)


实现类 StudentDaoImpl.java

public class StudentDaoImpl implements StudentDao {

    @Override
    public List<Student> selectStudents() {

        //获取SqlSession对象
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        String sqlId = "com.zh.dao.StudentDao.selectStudents";
        //执行sql语句,用SqlSession类里面的方法
        List<Student> students = sqlSession.selectList(sqlId);
        //关闭事务
        sqlSession.close();
        return students;
    }
}

测试类

public class TestMyBatis {
    @Test
    public void testSelectStudent(){

        StudentDao Dao = new StudentDaoImpl();
        List<Student> students = Dao.selectStudents();
        for (Student student: students){
            System.out.println(student);
        }
    }
}

2、JDK动态代理(重点)


不用创建实现类,直接调用 SqlSession.getMapper(dao接口.class),就可以得到dao接口的实现类

public class TestMyBatis {
    @Test
    public void testSelectStudent(){

        /*
        * 使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口.class)
        * getMapper能获取dao接口对应的实现类对象
        *
        * */
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);	//重点

        System.out.println("dao="+dao.getClass().getName());//dao=com.sun.proxy.$Proxy2,JDK动态代理

        List<Student> students = dao.selectStudents();
        for (Student student : students){
            System.out.println("学生"+student);
        }
    }
}




传入参数

把数据传入映射文件的sql语句中


传入参数的几种方式

1	一个简单类型的参数:#{任意字符}
2 	多个简单类型的参数,使用 @Param"自定义名称"3	使用一个java对象,对象的属性值作为mapper文件找到参数,#{java对象的属性值名称}

1、一个简单类型的参数

简单类型:mybatis把java的 基本数据类型 和 String 都叫简单类型
在mapper文件获取简单类型的一个参数的值,使用 #{任意字符},这个是:id=#{id}

接口方法

//按ID查询,参数是Integer类型,返回值类型是Student类型
public Student selectStudentById(Integer id);

映射文件语句

<select id="selectStudentById" resultType="com.zh.entity.Student" parameterType="java.lang.Integer">
    select id,name,email,age from student where id=#{id}
</select>

对应的测试方法

@Test
public void testSelectStudentById(){

    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    Student student = dao.selectStudentById(2);
    System.out.println("student="+student);

}

2、传递多个参数


a、在形参定义的前面加入 @Param(“自定义参数名称”)


接口

public List<Student> selectMulitParam(@Param("myname") String name,@Param("myage") String age)

映射文件

<select>
	select id,name,email,age from student where name=#{myname} or age=#{myage}
</select>

测试方法

//多参查询 @param 命名参数
@Test
public void testSelectMultiParam(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    List<Student> students = dao.selectMultiParam("梁家辉", 33);
    System.out.println("students="+students);

    sqlSession.close();
}

b、使用java对象作为接口中方法的参数


先定义一个实体类 QueryParam.java

package com.zh.vo;
public class QueryParam {

    private String paramName;
    private Integer paramAge;

    public String getParamName() {return paramName;}
    public void setParamName(String paramName) {this.paramName = paramName;}
    public Integer getParamAge() {return paramAge;}
    public void setParamAge(Integer paramAge) { this.paramAge = paramAge;}}
}

接口

List<Student> selectMultiObject(QueryParam param);

mapper文件

<select id="selectMultiObject" resultType="com.zh.entity.Student">
    select * from Student where name=#{paramName} or age=#{paramAge}
</select>

测试方法

//多参查询 对象方式
@Test
public void testSelectMultiObject(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    QueryParam queryParam = new QueryParam();
    queryParam.setParamName("李小龙");
    queryParam.setParamAge(32);

    List<Student> students = dao.selectMultiObject(queryParam);
    System.out.println("students="+students);

    sqlSession.close();
}



“#” 和 “$” 的区别

1	#是占位符,表示列值的,放在等号右侧
2	$是占位符,表示字符串的连接,把sql语句连接成一个字符串
3	#使用JDBC指定PreparedStatement对象执行SQL语句,效率高,没有sql注入的风险
4	$使用Starement对象执行sql,效率低,有sql注入的风险



封装Mybatis输出结果


在这里插入图片描述

1、resultType

1	resultType 结果类型,指sql语句执行完成后,数据转为java对象,java类型是任意的
	resultType 结果类型,它的值
						1、类型的全限定名称
						2、类型的别名,例如 java.lang.Integer的别名为int

接口方法

public Student selectStudentById(Integer id);

mapper映射

<select id="selectStudentById" resultType="com.zh.entity.Student" >
       select id,name,email,age from student where id=#{id}
</select>


测试方法

@Test
public void testSelectStudentById(){

    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    Student student = dao.selectStudentById(2);

    System.out.println("student="+student);

}

2、resultMap

resultMap 可以自定义sql的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。常用在列名和 java 对象属性名不一样的情况。


自定义类型的别名

1	在mybatis主配置文件中定义,使用 <typeAlias> 定义别名
2	可以在resultType中使用自定义别名

resultMap 结果映射,指定列名和java对象属性的对应关系

1	你自定义列值赋值给哪个属性
2	当你的列名和属性名不一样时,一定使用resultMap

接口

 //使用resultMap定义映射关系
 List<Student> selectAllStudent();

mapper映射文件

<resultMap id="StudentMap" type="com.zh.entity.Student">
            <!--column 列名,property java类型的属性名 -->
            <id property="id" column="id"/>
            <result property="name" column="name"/>
            <result property="email" column="email"/>
            <result property="age" column="age"/>
</resultMap>

<!--使用resultMap-->
<select id="selectAllStudent" resultMap="StudentMap">
    select id,name,email,age from student
</select>

3、当查询的列名和类中属性名不一样时


方式一

自定义MyStudent类,这里属性定义分别为:stuid,stuname,stuemail,stuage

package com.zh.entity;

public class MyStudent {

    private Integer stuid;
    private String stuname;
    private String stuemail;
    private Integer stuage;

    public Integer getStuid() { return stuid;}
    public void setStuid(Integer stuid) { this.stuid = stuid;}
    public String getStuname() {return stuname;}
    public void setStuname(String stuname) { this.stuname = stuname;}
    public String getEmail() { return stuemail;}
    public void setEmail(String email) { this.stuemail = email;}
    public Integer getStuage() {return stuage;}
    public void setStuage(Integer stuage) { this.stuage = stuage;}
    @Override
    public String toString() {
        return "myStudent{" +
                "stuid=" + stuid +
                ", stuname='" + stuname + '\'' +
                ", email='" + stuemail + '\'' +
                ", stuage=" + stuage +
                '}';
    }
}

mapper映射文件,这里student表的属性分别为:id,name,email,age和自定义MyStudent类中属性不一致,这时用resultMap映射关系

<!-- type映射地址是:com.zh.entity.MyStudent.java -->
<resultMap id="myStudentMap" type="com.zh.entity.MyStudent">
    <!--
		 column:别名 
	     property: java类型的属性名 
	-->
    <id property="stuid" column="id"/>
    <result property="stuname" column="name"/>
    <result property="stuemail" column="email"/>
    <result property="stuage" column="age"/>
</resultMap>

<!--要查的sql列名和 MyStudent.java 属性名不一样-->
<select id="selectMyStudent" resultMap="myStudentMap">
    select id,name,email,age from student
</select>

方式二

mapper映射: 直接在sql语句中添加 ( as 对象属性名,简单常用)

<!--resultType的默认原则是:同名的列值赋值给同名的属性,使用列别名(java对象属性名)--->
<select id="selectDiffColProperty" resultType="com.zh.entity.MyStudent">
    select id as stuid,name as stuname,email as stuemail,age as stuage from student
</select>

4、like 模糊查询

在java代码中指定like的内容


接口

//第一种模糊查询,在java代码指定like的内容
List<Student> selectLikeOne(String name);

mapper映射

<!--第一种like,java代码指定like的内容-->
<select id="selectLikeOne" resultType="com.zh.entity.Student">
    select id,name,email,age from student where name like #{name}
</select>

测试类

@Test
public void testSelectLikeOne(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    //定义一个String类型的值
    String name = "%周%";
    List<Student> students = dao.selectLikeOne(name);

    for (Student stu : students){
        System.out.println(stu);
    }
    sqlSession.close();

}

结果如下

在这里插入图片描述


动态sql(重点)



sql内容是变化的,可以根据条件获取到不同的sql语句。主要是where部分发生变化。

动态sql的实现,使用的是mybatis提供的标签,< if >,< where >,< foreach >


1、< if >是判断条件

语法:
<if test="判断java对象的属性值">
部分sql语句
</if>

2、 < where >用来包含多个< if >

当多个 if 有一个成立时,< where >会自动生成一个WHERE关键字,并去掉 if 中多余的and,or等

<where>
    <if> </if>
    <if> </if>
</where>

接口

//where
List<Student> selectStudentWhere(Student student);

mapper映射

<select id="selectStudentWhere" resultType="com.zh.entity.Student">
    select id,name,email,age from student
    <where>
        <if test="name != null and name != ''">
            name = #{name}
        </if>

        <if test="age > 0">
           or age = #{age}
        </if>
    </where>
</select>

测试

//where
@Test
public void testSelectStudentWhere(){
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    Student student = new Student();
    student.setName("周润发");
    student.setAge(20);
    List<Student> students = dao.selectStudentWhere(student);
    for (Student student1 : students){
        System.out.println("Where="+student1);
    }
    sqlSession.close();
}

结果如下
在这里插入图片描述


去掉一个student.setName(“周润发”);执行结果:
在这里插入图片描述


3、< foreach > 循环java中的数组,list集合

主要用在 sql 的 in语句中


用法一:根据id查询


接口

//foreach   
List<Student> selectForeachOne(List<Integer> idlist);

mapper映射

<!--foreach 方式一-->
<select id="selectForeachOne" resultType="com.zh.entity.Student">
    select * from student where id in
    <foreach collection="list" item="myid" open="(" close=")" separator=",">
        #{myid}
    </foreach>

</select>

测试

//foreach 方式一
@Test
public void testSelectForeachOne() {
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    //定义一个list数组
    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);

    List<Student> students = dao.selectForeachOne(list);
    for (Student student : students) {
        System.out.println("foreach=" + student);
    }
}

用法二:根据对象属性查询


接口

//foreach   用法二 根据对象属性查询
List<Student> selectForeachTwo(List<Student> stulist);

mapper

<!--foreach 方式二-->
<select id="selectForeachTwo" resultType="com.zh.entity.Student">
    select * from student where id in
    <foreach collection="list" item="stu" open="(" close=")" separator=",">
        #{stu.id}
    </foreach>

</select>

测试

//foreach 方式二
@Test
public void testSelectForeachTwo() {
    SqlSession sqlSession = MyBatisUtils.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);

    List<Student> stuList = new ArrayList<>();

    Student s1 = new Student();
    s1.setId(1);
    stuList.add(s1);

    Student s2 = new Student();
    s2.setId(2);
    stuList.add(s2);

    List<Student> students = dao.selectForeachTwo(stuList);
    for (Student student : students) {
        System.out.println("foreach=" + student);
    }
}

结果如下
在这里插入图片描述


单独定义sql代码片段,替代相同sql语句

mapper映射

<!--定义sql片段-->
    <sql id="studentSql">
        select id,name,email,age from student
    </sql>

    <select id="selectStudentIf" resultType="com.zh.entity.Student">
--         select id,name,email,age from student
        <include refid="studentSql"/>
        where id > 0
        <if test="name != null and name != ''">
            name = #{name}
        </if>

        <if test="age >0">
            or age > #{age}
        </if>
    </select>



数据库属性 配置文件


把数据库连接信息放到一个单独的文件中。便于修改,保存,处理多个数据库信息。

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssh
jdbc.username=root
jdbc.password=137171

mybatis.xml

<!--指定properties文件位置,从根路径开始找文件-->
<properties resource="jdbc.properties"/>

<environments default="one">

    <environment id="one">
        <transactionManager type="JDBC"/>
        <dataSource type="POOLED">
            <property name="driver" value="#{jdbc.driver}"/>
            <property name="url" value="#{jdbc.url}"/>
            <property name="username" value="#{jdbc.username}"/>
            <property name="password" value="#{jdbc.password}"/>
        </dataSource>
    </environment>

jdbc.properties文件位置
在这里插入图片描述



sql映射读取


方法一:指定多个mapper文件


方法二:使用包名

​ name:mapper文件所在的包名,包中所有xml一次性加载,要求:

​ 1、mapper文件名需要和接口名一样
​ 2、mapper文件和dao接口在同一目录下


实例如下

<!--sql映射文件的位置-->
<mappers>
    <!--方法一:指定多个mapper文件-->
    <mapper resource="com/zh/dao/StudentDao.xml"/>

    <!--方法二:使用包名
        name:mapper文件所在的包名,包中所有xml一次性加载
        要求:
        1   mapper文件名需要和接口名一样
        2   mapper文件和dao接口在同一目录下
    -->
    <package name="com.zh.dao"/>
</mappers>

b站地址

https://www.bilibili.com/video/BV185411s7Ry

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页