框架之Mybatis学习

1、maven
一种辅助工具,对程序中用到的jar包进行管理,及jar包之间的依赖关系。
1)maven三要素
groupId(公司的标识,表明该项目所属的公司)
artifactId(项目的唯一标识,也可理解为项目名)
version版本(SNAPSSHOT快照版,也可理解为测试版),(RELEASE发布版
,也可理解为稳定版)
2)maven项目的目录结构不同以往的java项目目录,有一个src目录,还有
一个pom.xml文件。其src目录下多了main目录以及test目录,main目录下又
包含java与resources目录,java目录下放的是java源代码,resources目录
下放的是程序的配置文件及mapper映射文件;test目录下包含java目录,放
的是java测试代码。pom.xml文件下放的是maven项目自身的配置文件(一些
框架的jar包依赖)

 

2、mybatis属于ORM型框架,是通过关系型数据库与实体类间的映射关系
来简化数据库操作的一种框架。

 

2.1
1)在main目录下的java目录下写实体类
```
package entity;

import java.io.Serializable;

public class Emp implements Serializable {
    private int id;
    private String name;
    private int age;

    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 int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
```
2)在resources下新建一个mapper包,里面放各种映射文件
```
<?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="mapper.EmpMapper">
    <insert id="insert" parameterType="entity.Emp"
    useGeneratedKeys="true"
    keyColumn="id"
            keyProperty="id"
    >
    insert into emp(id,name,age) values(null,#{name},#{age})
    </insert>
    <delete id="delete" parameterType="list">
        delete from emp where id in
        <foreach collection="list" item="i" open="(" close=")" separator=",">
            #{i}
        </foreach>
    </delete>
    <!--<select id="selectByCondition" parameterType="map" resultType="entity.Emp">
        select * from emp where 1=1
        <if test="name !=null ">
            and name like #{name}
        </if>
        <if test="minAge !=null and maxAge !=null">
            and age between #{minAge} and #{maxAge}
        </if>
    </select>-->
    <select id="selectByCondition" parameterType="map" resultType="entity.Emp">
        select * from emp
        <!--使用where标签可以去掉多余的and-->
        <where>
        <if test="name !=null ">
            and name like #{name}
        </if>
        <if test="minAge !=null and maxAge !=null">
            and age between #{minAge} and #{maxAge}
        </if>
        </where>
    </select>
    <update id="update" parameterType="entity.Emp">
        update emp
        <set>
            <if test="name !=null">
                name= #{name},
            </if>
            <if test="age !=0">
                age= #{age}
            </if>
        </set>
        where id=#{id}
    </update>
    <select id="selectByPage" parameterType="map" resultType="entity.Emp">
        select * from emp limit #{index},#{number }
    </select>
    <select id="selectByLogical" resultType="entity.Emp">
        select * from emp;
    </select>
</mapper>
```
3)在resources目录下建一个mybatis-config.xml文件,是mybatis的配置文件
,主要配置如何连接数据库,以及相应的映射文件
```
<?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.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/test3?
                serverTimezone=GMT%2B8&amp;useSSL=false&amp;useServerPrepStmts
                =true&amp;cachePrepStmts=true&amp;rewriteBatchedStatements=true
                &amp;useCursorFetch=true&amp;defaultFetchSize=100&amp;
                allowPublicKeyRetrieval=true"/>
                <property name="username" value="root"/>
                <property name="password" value="9315"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <!-- 让mabatis知道有哪些映射文件 -->
        <mapper resource="mapper/User1Mapper.xml"/>
        <mapper resource="mapper/EmpMapper.xml"/>
        <mapper resource="mapper/DogMapper.xml"/>
        <mapper resource="mapper/ProductMapper.xml"/>
    </mappers>
</configuration>
```
4)在test目录下编写测试代码
4.1)获取配置文件的输入流
```
InputStream resource = Resources.getResourceAsStream("mybatis-config.xml");
```
4.2)创建SqlSessionFactory工厂类对象
```
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(resource);
```
4.3)创建SqlSession对象
```
SqlSession sqlSession = factory.openSession();
```
4.4)进行sql语句操作
```
sqlSession.insert("mapper.EmpMapper.insert",emp);
```
4.5)提交事务
```
sqlSession.commit();
```
4.6)关闭资源
```
sqlSession.close();
```

 

2.2
1)
(  
1.1)新增,获取自增长值;
1.2)动态sql,一次删除多条信息;
1.3)动态sql,按条件查询;
1.4)动态更新,修改姓名或是年龄任意一项时,不用依赖于另一项的条件;
1.5)物理分页查询,效率高,但是不通用,数据库改变,sql语句也得改变;
1.6)逻辑分页查询,查询全部数据,因而效率低,但是通用,适用于数据量
较少的情况

相关代码
```
<?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="mapper.EmpMapper">
    <!--获取自增长的值,将数据库插入后生成的id值,同步到java对象
    useGeneratedKeys="是否使用由数据库生成的主键"
     keyColumn="主键列的名称"
     keyProperty="主键要存入哪个属性"-->
    <insert id="insert" parameterType="entity.Emp"
    useGeneratedKeys="true"
    keyColumn="id"
            keyProperty="id"
    >
    insert into emp(id,name,age) values(null,#{name},#{age})
    </insert>
    <!--动态删除,一次删除多个
    collection="要遍历的集合"
    item="临时变量名称"
    open="循环之前的符号"
    close="循环之后的符号"
    separator="每个元素的分隔符"-->
    <delete id="delete" parameterType="list">
        delete from emp where id in
        <foreach collection="list" item="i" open="(" close=")" separator=",">
            #{i}
        </foreach>
    </delete>
    <!--<select id="selectByCondition" parameterType="map" resultType="entity.Emp">
        select * from emp where 1=1
        <if test="name !=null ">
            and name like #{name}
        </if>
        <if test="minAge !=null and maxAge !=null">
            and age between #{minAge} and #{maxAge}
        </if>
    </select>-->
    <!--按条件查询-->
    <select id="selectByCondition" parameterType="map" resultType="entity.Emp">
        select * from emp
        <!--使用where标签可以去掉多余的and-->
        <where>
        <if test="name !=null ">
            and name like #{name}
        </if>
        <if test="minAge !=null and maxAge !=null">
            and age between #{minAge} and #{maxAge}
        </if>
        </where>
    </select>
    <update id="update" parameterType="entity.Emp">
        update emp
        <set>
            <if test="name !=null">
                name= #{name},
            </if>
            <if test="age !=0">
                age= #{age}
            </if>
        </set>
        where id=#{id}
    </update>
    <!--物理分页查询,不通用,数据库不同sql语法有差异,但效率高-->
    <select id="selectByPage" parameterType="map" resultType="entity.Emp">
        select * from emp limit #{index},#{number }
    </select>
    <!--逻辑分页查询,查询所有,通用,效率低,适合数据较少的情况-->
    <select id="selectByLogical" resultType="entity.Emp">
        select * from emp;
    </select>
</mapper>
```
```
import entity.Emp;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class TestEmp {
    static SqlSessionFactory factory;
    static {
        try {
            InputStream resource = Resources.getResourceAsStream("mybatis-config.xml");
            factory=new SqlSessionFactoryBuilder().build(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    //插入数据,依赖建表规则实现主键的自增
    public void test1(){
        SqlSession sqlSession = factory.openSession();
        Emp emp = new Emp();
        System.out.println("插入之前的id:"+emp.getId());
        emp.setName("金秀贤");
        emp.setAge(35);
        sqlSession.insert("mapper.EmpMapper.insert",emp);
        sqlSession.commit();
        sqlSession.close();
        System.out.println("插入之后的id:"+emp.getId());
    }
    @Test
    //一次删除多条数据
    public void test2(){
        SqlSession sqlSession = factory.openSession();
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        sqlSession.delete("mapper.EmpMapper.delete",list);
        sqlSession.commit();
        sqlSession.close();
    }
    @Test
    //按条件查询
    public void test3(){
        SqlSession sqlSession = factory.openSession();
        HashMap<String, Object> map = new HashMap<>();
        //map.put("name","李%");
        map.put("minAge",21);
        map.put("maxAge",35);
        List<Emp> list = sqlSession.selectList("mapper.EmpMapper.selectByCondition", map);
        sqlSession.commit();
        sqlSession.close();
        for (Emp object:list){
            System.out.println(object);
            System.out.println("_________________________________________________");
        }
    }
    @Test
    //修改姓名或是年龄任意一项时,不用依赖于另一项的条件
    public void test4(){
        SqlSession sqlSession = factory.openSession();
        Emp emp = new Emp();
        emp.setAge(33);
        emp.setId(5);
        sqlSession.update("mapper.EmpMapper.update",emp);
        sqlSession.commit();
        sqlSession.close();
    }
    @Test
    //分页查询1(物理查询,数据库类型改变,sql代码也会改变)
    public void test5(){
        SqlSession sqlSession = factory.openSession();
        HashMap<String, Object> map = new HashMap<>();
        map.put("index",4);
        map.put("number",4);
        List<Emp> list = sqlSession.selectList("mapper.EmpMapper.selectByPage",map);
        Iterator<Emp> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
            System.out.println("_____________________________________");
        }
        sqlSession.close();
    }
    @Test
    //分页查询2(逻辑查询,查询所有,效率低,sql语句不因数据库类型的改变而改变,兼容性强)
public void test6(){
        SqlSession sqlSession = factory.openSession();
        List<Emp> list = sqlSession.selectList("mapper.EmpMapper.selectByLogical", null, 
        new RowBounds(4, 4));
        sqlSession.close();
        Iterator<Emp> iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
            System.out.println("__________________________________________");
        }
    }
}
```
 
2)数据库表中的数据与实体类的属性不匹配时
(
  1)使用别名来解决该问题;
  2)使用resultMap代替resultType

相关代码:
```
package entity;

import java.io.Serializable;

public class Dog implements Serializable {
    private int id;
    private String firstName;
    private String lastName;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "id=" + id +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                '}';
    }
}
```
```
<?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="mapper.DogMapper">
    <!--方法一,采用别名解决-->
  <!--  <select id="select" parameterType="int" resultType="entity.Dog">
     &lt;!&ndash;select id,first_name,last_name from dog where id=#{id}&ndash;&gt;
        select id,first_name firstName,last_name lastName from dog where id= #{id}
    </select>-->
    <!--方法二,使用resultMap代替resultType-->
    <select id="select" parameterType="int" resultMap="mm">
        select id,first_name,last_name from dog where id=#{id}
    </select>
    <!--id:主键列,result:其余列;column:数据库对应的列名;property:数据库列对应的实体类的属性名
     type="实体对象的类型"
     id 标签用来映射主键
     result 标签用来映射其它列-->
    <resultMap id="mm" type="entity.Dog">
        <id column="id" property="id"></id>
        <result column="first_name" property="firstName"></result>
        <result column="last_name" property="lastName"></result>
    </resultMap>
</mapper>
```
```
import entity.Dog;
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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class DogTest {
    static SqlSessionFactory factory;
    static {
        //获取配置文件的输入流
        try {
            InputStream resource = Resources.getResourceAsStream("mybatis-config.xml");
            factory=new SqlSessionFactoryBuilder().build(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    //查询(当数据库的属性名和java中的实体类的属性不一致时)
    public void test1(){
        SqlSession sqlSession = factory.openSession();
        Dog dog= sqlSession.selectOne("mapper.DogMapper.select",2);
        sqlSession.close();
        System.out.println(dog);
    }
            }
```
3)
(
 1)当数据库中多个表之间存在连接关系时,想要获得多个表的信息时,
 ,把连接查询映射到多个有关系的实体类上;
 2)mybatis中的一级缓存,每一个SqlSession都有一个一级缓存,只有在
 首次查询数据库时,会把结果放入到缓存中,缓存中是以map键值对的形式
 存储信息的,查询语句相当于键,结果相当于值,只要后续执行相同的sql
 语句,就会直接从一级缓存中获取结果,不会再去查询数据库,作用范围
 仅限同一个SqlSession对象;
 3)mybatis中的二级缓存,其意义在于减少与数据库的交互,提高效率,不同于
 一级缓存的地方是,它需要在对应的映射文件中的mapper标签下加一个 <cache/>
 标签,这样,该映射文件中的所有查询操作都可以共享二级缓存了;
 4)以上两种缓存,只要对数据库表执行了增、删、改操作,便会立即失效,
 再次执行相同的查询语句,它会首先去数据库中查,不会去缓存中找了;
 5)#{}与${}的区别
 #{}是以占位符的方式生成sql语句,能够防止sql注入攻击,但是#{}不能进行
 运算操作,不能对表名、列名进行改动,只能替换值;${}是以拼接字符串的方式生成sql语句,
 不安全,但是能够进行运算操作,可以替换sql语句的任何部分
 )
 
 相关代码
 ```
package entity;

import java.io.Serializable;

public class Product implements Serializable {
    private int id;
    private String name;
    private double price;
    private Category category;

    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 double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public Category getCategory() {
        return category;
    }
    public void setCategory(Category category) {
        this.category = category;
    }
    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", category=" + category +
                '}';
    }
}
```
```
package entity;

import java.io.Serializable;

public class Category implements Serializable {
    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;
    }
    @Override
    public String toString() {
        return "Category{" +
                "id=" + id +
                ", name='" + 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="mapper.ProductMapper">
    <!--二级缓存配置方法-->
    <cache/>
    <!--连接查询,当多个表之间有连接关系时,想把有连接关系
    的表的信息也显示出来-->
<select id="select" parameterType="int" resultMap="kkk">
        select p.id,p.name,p.price,c.id cid,c.name cname from product p inner
        join category c on p.category_id=c.id where p.id=#{id}
    </select>
<resultMap id="kkk" type="entity.Product">
    <id column="id" property="id"></id>
    <result column="name" property="name"></result>
    <result column="price" property="price"></result>
    <!--association关联-->
    <association property="category" javaType="entity.Category">
        <id column="cid" property="id"></id>
        <result column="cname" property="name"></result>
    </association>
</resultMap>
    <!--一级缓存-->
    <select id="select1" parameterType="int" resultType="entity.Product">
        select id,name,price from product where id=#{id}
    </select>
    <update id="update" parameterType="entity.Product">
        update product set price= ${price+500} where id= #{id}
    </update>
</mapper>
```
```
import entity.Product;
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 org.junit.Test;

import java.io.IOException;
import java.io.InputStream;

public class ProductTest {
    static SqlSessionFactory factory;
    static {
        try {
            //获取配置文件的输入流
            InputStream resource = Resources.getResourceAsStream("mybatis-config.xml");
           //创建SqlSession工厂类
            factory = new SqlSessionFactoryBuilder().build(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    public void test1(){
        //创建SqlSession对象
        SqlSession sqlSession = factory.openSession();
        Product product = sqlSession.selectOne("mapper.ProductMapper.select", 1);
        System.out.println(product);
        System.out.println("_____________________");
        System.out.println(product.getCategory());
    }
    @Test
    public void test2(){
        SqlSession sqlSession1 = factory.openSession();
        Product product1 = sqlSession1.selectOne("mapper.ProductMapper.select1", 1);
        System.out.println("___________________________________");
        Product product2 = sqlSession1.selectOne("mapper.ProductMapper.select1", 1);
        System.out.println("___________________________________");
        Product product3 = sqlSession1.selectOne("mapper.ProductMapper.select1", 2);
        sqlSession1.close();
        System.out.println("________________________________________");
        SqlSession sqlSession2 = factory.openSession();
        Product product4 = sqlSession2.selectOne("mapper.ProductMapper.select1", 1);
        sqlSession2.close();
    }
    @Test
    public void test3(){
        SqlSession sqlSession = factory.openSession();
        Product product = new Product();
        product.setPrice(2499);
        product.setId(1);
        sqlSession.update("mapper.ProductMapper.update",product);
        sqlSession.commit();
        sqlSession.close();
    }
}
```
 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值