个人Mybatis复习篇

Mybatis

SqlMapConfig.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">
<!--mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务类型-->
            <transactionManager type="JDBC"></transactionManager>
           <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置连接数据库的基本信息-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
    <mappers>
        <mapper resource=""/>

    </mappers>

</configuration>

UserDao.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="dao.UserDao">
    <!--配置查询所有-->
    <select id="findAll">
        select * from user;
    </select>


</mapper>

log4j.properties

### 设置###
log4j.rootLogger = debug,stdout,D,E
 
### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n
 
### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
 
### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

创建实体类时为什么要实现序列化

1,什么是Serializable接口

一个对象序列化的接口,一个类只有实现了Serializable接口,它的对象才能被序列化。

2,什么是序列化?

序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。

3,为什么要序列化对象

把对象转换为字节序列的过程称为对象的序列化

把字节序列恢复为对象的过程称为对象的反序列化	

4,什么情况下需要序列化?

当我们需要把对象的状态信息通过网络进行传输,或者需要将对象的状态信息持久化,以便将来使用时都需要把对象进行序列化

Mybatis关于动态数据库

Mybaties关于表之间的关系

1,mybatis中的多表查询

表之间的关系有几种:

	一对多,多对一,一对一,多对多

举例:

	用户和订单就是多对一

		一个用户可以下多个订单

		多个订单属于一个用户

	人和身份证之间一对一

		一个人只能有一个身份证号

		一个身份证只属于一个人

	多对多

		一个学生被多个老师教过

		一个老师可以教多个学生

特例:

	在一定期限内,用户购买多个订单,如果从最近的一天拿出一个订单,它也只能属于一个用户,所以mybatis就把多对一看成一对一

1,mybatis的多表查询

示例:用户和账户

	一个用户可以有多个账户

	一个账户只能属于一个用户(多个账户也可以属于一个用户)

步骤:

	1,建立两张表,用户表和账户表

		让用户表和账户表之间具有一对多的关系,需要使用外键在账户表中

	2,建立两个实体类,用户实体类和账户实体类

		让用户和账户的实体类能体现出一对多的关系

	3,建立两个配置文件

		用户配置文件

		账户配置文件

	4,实现配置

		当我们查询用户时,可以同时查询到用户下所包含的账户信息

		当我们查询账户时,可以同时查询到账户所属的用户信息

mybatis中的延迟加载

问题:在一对多中,当我们有一个用户,他有100个账户

	    在查用户时候,要不要关联的账户查出来?

	     在查询账户的时候,要不要把关联的用户查出来?

		

	     在查询用户时,用户下的账户信息应该是什么时候用,什么时候查询

	      在查询账户时,账户的所属用户信息应该时随着账查询时一起被查询出来

什么是延迟加载

	在真正使用数据时才能发起查询,不用的时候不查询,按需查询(懒查询)

什么是立即加载

	不管用不用,只要一调用方法,马上发起查询

在对应的四种查询表的关系中,一对一,一对多,多对一,多对多

	一对多,多对多:通常情况下我们都是采用延迟加载

	一对一,多对一:通常情况下采用的是立即加载

mybatis中的缓冲

什么是缓冲

	存在于内存中的临时数据

为什么使用缓冲

	减少和数据库的交互次数,提高执行效率

什么样的数据能使用缓冲,什么样的数据不需要使用

	适用于缓冲:

		经常查询并且不发生改变的数据

		数据的正确与否对最终结果影响不大的

	不适用缓冲

		经常发生改变的数据

		数据的正确对结果影响很大

		例如:股市的牌价,商品的库存,银行的汇率

Mybatis中的一级缓冲和二级缓冲		

	一级缓冲:

		它指的是Mybatis中的SqlSession对象的缓冲

		当我们执行查询之后,查询的结果会同时存入到SqlSession位我们提供的一块区域当中,该区域的结果是一个Map,当我们再次查同样的数据,Mybatis会先去SqlSession当中查询数据是否有,如果有拿来直接用

		当SqlSession对象小时或者关闭后,mybaties中的一级缓冲也小时了

        User user1=userDao.findById(1);
        System.out.println(user1);

//        session.close();
//        //再次获取对象
//        SqlSession session=factory.openSession();
        session.clearCache();//此方法也可清除缓存

        UserDao userDao=session.getMapper(UserDao.class);

        User user2=userDao.findById(1);
        System.out.println(user2);

        System.out.println(user1==user2);
    }		

二级缓存:

	它指的是Mybatis中的SqlSessionFactory对象的缓存,由同一个SqlSessionFactory对象创建的SqlSession共享其缓存

	二级缓冲使用步骤:

		第一步:让Mybatis框架支持二级缓冲(在SqlMapConfig.xml中配置)

		第二步:让当前的映射文件支持二级缓存(在UserDao.xml中配置)

		第三步:让当前的操作文件支持二级缓存(在select标签中配置)

mybatis再来一遍

思路:搭建环境->导入mybatis->编写代码->测试

搭建数据库

create database mybatis;

use mybatis;

create table user(
 id int(20) not null primary key,
 name varchar(20) default null,
 pwd varchar(30) default null
)engine=innodb default charset=utf8;

insert into user(id,name,pwd) values
(1,'张三','123456'),
(2,'李四','123455'),
(3,'王五','135421')

select * from user;

新建项目

1,新建一个maven工程

2,删除src目录

3,导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <!--父工程-->
    <groupId>com.mjn</groupId>
    <artifactId>day01study</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <!--子模块-->
    <modules>
        <module>mybatis-01</module>
    </modules>

    <!--导入依赖-->
    <dependencies>
        <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.6</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

</project>

2.2 创建一个模块

*编写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/mybatis?useSSL=true&amp;userUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=GMT"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/mjn/dao/UserMapper.xml"/>
    </mappers>
</configuration>

*编写SqlSessionFactory----->sqlSession的工具类

package com.mjn.utils;

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 java.io.IOException;
import java.io.InputStream;

//SqlSessionFactory---->sqlSession
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,我们就可以获取sqlSession实例了
    //sqlSession中含有数据库执行sql的命令
    public static SqlSession getSqlSession(){
        SqlSession sqlSession=sqlSessionFactory.openSession();
        return sqlSession;
    }
}

2.3 编写代码

  • 实体类
    package com.mjn.pojo;
    //实体类
    public class User {
    private int id;
    private String name;
    private String pwd;

        public User() {
        }
    
        public User(int id, String name, String pwd) {
            this.id=id;
            this.name=name;
            this.pwd=pwd;
        }
    
        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 String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd=pwd;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    '}';
        }
    }
    
  • Dao接口
    package com.mjn.dao;

    import com.mjn.pojo.User;
    
    import java.util.List;
    
    public interface UserDao {
    
        List<User> getUserList();
    }
    
  • 接口实现类由原来的UserDaoImpl转换为一个Mapper配置文件
    <?xml version="1.0" encoding="UTF-8"?>





    select * from User where id=#{id};


    2.4 测试
    错误1
    Type interface com.mjn.dao.UserDao is not known to the MapperRegistry
    未在mybatis-config.xml配置文件中注册
    错误2
    Error parsing SQL Mapper Configuration. Cause: java.io.IOException: Could not find resource com.mjn.dao/Mapper.xml
    需要在pom.xml文件中添加过滤




    src/main/resources

    /*.properties
    /.xml

    true


    src/main/java

    **/.properties
    **/*.xml

    true


测试代码:

package com.mjn.dao;

import com.mjn.pojo.User;
import com.mjn.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.List;

public class UserDaoTest {
    @Test
    public void test(){
        //获取sqlSession对象
        SqlSession sqlSession=MybatisUtils.getSqlSession();
        //执行sql语句
        //方式1 getMapper
        UserDao userDao=sqlSession.getMapper(UserDao.class);

        List<User> userList=userDao.getUserList();

        for (User user : userList) {
            System.out.println(user);
        }

        //关闭sqlSession
        sqlSession.close();
    }
}

3 CRUD

1,namespace

namespace中的包名要和Dao/Mapper接口的包名一致

2,select

选择,查询语句

  • id:就是对应的namespace中的方法名
  • resultType:sql语句执行的返回值
  • parameterType:参数

1,编写接口

    //根据id查询用户
    User getUserById(int id);

2,编写mybatis.xml配置文件填写相应的sql语句

<select id="getUserById" resultType="com.mjn.pojo.User" parameterType="int">
    select * from mybatis.user where id=#{id}
</select>

3,测试根据id查询语句

@Test
public void getUserById(){
    //获取SqlSession
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    //获取dao中的mapper对象
    UserMapper mapper=sqlSession.getMapper(UserMapper.class);
    //使用mapper对象查询
    User user=mapper.getUserById(1);

    System.out.println(user);

    sqlSession.close();
}

3 insert

//添加用户信息
int addUser(User user);

<insert id="addUser" parameterType="com.mjn.pojo.User">
    insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd})
</insert>

@Test
//增删改查需要提交事务
public void addUser(){
    //获取SqlSession
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    //获取dao中的mapper对象
    UserMapper mapper=sqlSession.getMapper(UserMapper.class);

    User user=new User();
    user.setId(4);
    user.setName("王麻子");
    user.setPwd("123458");

    mapper.addUser(new User(5,"武松","888453"));
    int i=mapper.addUser(user);

    System.out.println(i);

    sqlSession.commit();
    sqlSession.close();
}

4 delete

//删除用户
int deleteUser(int id);

<delete id="deleteUser" parameterType="int">
    delete from mybatis.user where id=#{id}
</delete>

@Test
//增删改查需要提交事务
public void deleteUser(){
    //获取SqlSession
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    //获取dao中的mapper对象
    UserMapper mapper=sqlSession.getMapper(UserMapper.class);

    int i=mapper.deleteUser(4);
    System.out.println(i);
    sqlSession.commit();
    sqlSession.close();
}

5 update

//修改用户
int updateUser(User user);

<update id="updateUser" parameterType="com.mjn.pojo.User">
    update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}
</update>

@Test
//增删改查需要提交事务
public void updateUser(){
    //获取SqlSession
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    //获取dao中的mapper对象
    UserMapper mapper=sqlSession.getMapper(UserMapper.class);


    int name=mapper.updateUser(new User(5, "鲁智深", "888888"));
    System.out.println(name);

    sqlSession.commit();
    sqlSession.close();
}

#注意,增删改需要添加事务

7 万能的map

//采用map集合的方式查询
User getUserById2(Map<String,Object> map);

<select id="getUserById2" parameterType="map" resultType="com.mjn.pojo.User">
    select * from mybatis.user where id=#{userId}
</select>

@Test
public void getUserById2(){
    //获取SqlSession
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    //获取dao中的mapper对象
    UserMapper mapper=sqlSession.getMapper(UserMapper.class);
    //使用mapper对象查询
    Map<String, Object> map=new HashMap<String, Object>();

    map.put("userId",2);
    User user=mapper.getUserById2(map);
    System.out.println(user);

    sqlSession.close();
}

Map传递参数,直接在Sql语句当中取出key即可【parameterType=“map”】

对象传递参数,直接在sql中取出对象的属性即可【parameterType=“Object”】

只有一个基本类型参数的情况下,可以直接在sql中取到

多个参数用Map,或者注解

8 模糊查询

1,Java代码执行的时候,传递通配符

    @Test
    public void getUserLike(){
        //获取SqlSession
        SqlSession sqlSession=MybatisUtils.getSqlSession();
        //获取dao中的mapper对象
        UserMapper mapper=sqlSession.getMapper(UserMapper.class);

        List<User> userList=mapper.getUserLike("%张%");

        for (User user : userList) {
            System.out.println(user);
        }

        sqlSession.close();
    }

2,在sql拼接中使用通配符

会出现sql

    <!--通过模糊查询-->
    <select id="getUserLike" resultType="com.mjn.pojo.User" parameterType="String">
        select * from mybatis.user where name like "%"#{value}"%"
    </select>

3.测试

@Test
public void getUserLike(){
    //获取SqlSession
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    //获取dao中的mapper对象
    UserMapper mapper=sqlSession.getMapper(UserMapper.class);

    List<User> userList=mapper.getUserLike("%张%");

    for (User user : userList) {
        System.out.println(user);
    }

    sqlSession.close();
}

4 配置环境

1 核心配置文件

mybatis-config.xml

2 环境配置

mybatis可以配置成适应多个环境

不过要记住,尽管可以配置多个环境,但是SqlSessionFactory实例只能选择一种环境

学会使用配置多套运行环境

Mybatis默认的事务管理器时JDBC,连接池POOLED

3 编写属性

编写一个db.properties外部配置文件

db.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&userUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT
username=root
password=root

在核心文件中映入

注意!!!:

核心配置文件当中属性是有次序的,不能随便书写

The content of element type “configuration” must match “(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)”.

<!--引入外部文件-->
<properties resource="db.properties"/>
  • 可以直接引入外部文件
  • 可以在properties属性当中添加一些属性配置
  • 如果两个文件有同一个字段(比如密码),会优先使用外部配置文件

4 类型别名(typeAliases)

  • 类型别名是为Java类型设置一个短的名字

  • 存在的意义仅用于减少类全限定类的冗余

也可以指定一个包名,Mybatis会在包下面搜索需要的JavaBean:比如

扫描实体的包,它的默认类名为!!首字母小写

<!--给实体类起别名-->
<typeAliases>
    <package name="com.mjn.pojo"/>
</typeAliases>

在实体类比较少的时候,使用第一种

如果较多就使用第二种

第一种可以DIY别名,第二种不行

也可在实体类上写注解@Aliases

@Alias("user")
public class User{}

5 映射器

MapperRegistry:注册绑定我们的Mapper文件

方式一:

<!--Mapper.xml都需要在mybatis-config.xml核心配置文件种注册-->
<mappers>
    <mapper resource="com/mjn/dao/UserMapper.xml"/>
</mappers>

方式二:

    <!--Mapper.xml都需要在mybatis-config.xml核心配置文件种注册-->
    <mappers>
<!--        <mapper resource="com/mjn/dao/UserMapper.xml"/>-->
    <mapper class="com.mjn.pojo"/>
    </mappers>

注意点:

  • 接口和它的Mapper配置文件必须同名!
  • 接口和它的Mapper配置文件必须在同一个包下

方式三:

    <mappers>
<!--        <mapper resource="com/mjn/dao/UserMapper.xml"/>-->
<!--    <mapper class="com.mjn.pojo"/>-->
    <package name="com.mjn.dao"/>
    </mappers>

注意点:

  • 接口和它的Mapper配置文件必须同名!
  • 接口和它的Mapper配置文件必须在同一个包下

6 生命周期和作用域

错误的使用会导致并发问题

7 结果集映射

id	name	pwd
id	name	password


<!--结果集映射-->
<resultMap id="UserMap" type="User">
	<!--column为数据库中的字段,property为实体类的属性-->
    <id column="pwd" property="password"/>
    <result column="name" property="name"/>
    <result column="id" property="id"/>
</resultMap>
<!--通过属性查询-->
<select id="getUserById" resultMap="UserMap" parameterType="int">
    select * from mybatis.user where id=#{id}
</select>

5 日志

5.1 日志工厂

<!--引入外部配置文件-->
<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

5.2 log4j

1,先导入jar包

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

2,log4j.properties

 ### 设置###
log4j.rootLogger = debug,stdout,D,E

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=E://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = E://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=E://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =E://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

3,配置log4j日志的实现

    <!--引入外部配置文件-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>

4,log4j的使用

1,在使用log4j的类中,导入包import org.apache.log4j.Logger;

2,日志对象,参数为当前类的class

static Logger logger=Logger.getLogger(UserDaoTest.class);

3,日志对象用法

package com.mjn.dao;

import com.mjn.pojo.User;
import com.mjn.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

public class UserDaoTest {

    static Logger logger=Logger.getLogger(UserDaoTest.class);

    @Test
    public void getUserById(){
        //获取SqlSession
        SqlSession sqlSession=MybatisUtils.getSqlSession();
        //获取dao中的mapper对象
        UserMapper mapper=sqlSession.getMapper(UserMapper.class);
        //使用mapper对象查询
        User user=mapper.getUserById(1);

        System.out.println(user);

        sqlSession.close();
    }

    @Test
    public void testLog4j(){
        logger.info("在E://logs/log.log中");
        logger.error("在E://logs/error.log 文件中");
        logger.debug("debug");
    }
}

6 分页

思考为什么要分页

  • 减少数据处理量

使用Limit分页

语法:SELECT * FROM USER LIMIT startIndex,pageSize;
	Select * from user limit 3;  #表示从0-3查询

使用Mybatis实现分页,核心SQL

1,接口

//分页查询
List<User> getUserByLimit(Map<String,Integer> map);

2,Mapper.xml

<!--使用分页查询-->
<select id="getUserByLimit" resultType="User" resultMap="UserMap" parameterType="map">
    select * from user limit #{startIndex},#{pageSize}
</select>

3,测试

@Test
public void getUserByLimit(){
    //通过工具类获取sqlSession对象
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    //实现映射
    UserMapper mapper=sqlSession.getMapper(UserMapper.class);
    //创建HashMap
    HashMap<String, Integer> map=new HashMap<String, Integer>();
    //向Map中插入值
    map.put("startIndex",0);
    map.put("pageSize",2);

    List<User> userList=mapper.getUserByLimit(map);
    for (User user : userList) {
        System.out.println(user);
    }
    sqlSession.close();
}

7 注解

1,注解在接口上实现

//注解查询
@Select("select * from user")
List<User> getUsers();

2,需要在核心配置文件当中绑定接口

<!--扫描Mapper-->
<mappers>
    <mapper class="com.mjn.dao.UserMapper"/>
</mappers>

3,测试

@Test
public void getUsers(){
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    UserMapper mapper=sqlSession.getMapper(UserMapper.class);
    List<User> users=mapper.getUsers();
    for (User user : users) {
        System.out.println(user);
    }
    sqlSession.close();
}

8 注解开发

CRUD

1,接口

//注解查询
@Select("select * from user")
List<User> getUsers();

//注解插入
@Insert("insert into user(id,name,pwd) values(#{id},#{name},#{pwd}")
int addUser(User user);

//注解删除
@Delete("delete from user where id=#{uid}")
int deleteUser(@Param("uid") int id);

//注解更新
@Update("update user set name=#{name},pwd=#{pwd} where id=#{id}")
int updateUser(User user);

2,测试

@Test
public void updateUser(){
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    UserMapper mapper=sqlSession.getMapper(UserMapper.class);
    int i=mapper.updateUser(new User(3, "李逵", "111111"));
    System.out.println(i);

    sqlSession.commit();

    sqlSession.close();
}

#注意

【我们必须要将接口注册绑定到核心配置文件中】

关于@Param()注解

  • 基本类型的参数或者string类型,需要加上
  • 引用类型不需要加
  • 如果只有一个基本类型,可以忽略,建议写上
  • 我们在sql中引入的是这里@Param()中的属性名
  • {} ¥{}比较 前者会避免sql注入问题,就像prepareStatement一样

9 Lombok

实现注解将实体类的gatter和setter等方法使用注解代替

10 多对一处理

数据库一个老师管理多个学生

多个学生对应一个老师

create table teacher(
	id int(10) not null,
	name varchar(30) default null,
	primary key(id)
)engine=INnodb default charset=utf8;

insert into teacher(id,name) values(1,"王老师");


create table student(
	id int(10) not null,
	name varchar(30) default null,
	tid int(10) default null,
	primary key(id),
	key fktid(tid),
	constraint fktid foreign key(tid) references teacher(id)
)engine=INNODB default charset=utf8;

insert into student(id,name,tid) values(1,"小红","1");
insert into student(id,name,tid) values(2,"小明","1");
insert into student(id,name,tid) values(3,"小王","1");
insert into student(id,name,tid) values(4,"小李","1");
insert into student(id,name,tid) values(5,"小张","1");


select * from student;
select * from teacher;

测试环境搭建

1,新建实体类teacher和student

2,建立两个实体类的Mapper接口

3,建立Mapper.xml文件

4,在核心配置文件中绑定注册我们的Mapper接口或者文件

5,测试查询是否成功

多对一

按照子查询

<!--
    1,查询所有的学生信息
    2,根据查询出来的学生id来查询对应的老师    子查询
-->
<select id="getStudent" resultMap="StudentTeacher">
    select * from student
</select>

<resultMap id="StudentTeacher" type="Student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <!--复杂的属性,我们需要单独处理,对象:association 集合:collection-->
    <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>

<select id="getTeacher" resultType="Teacher">
    select * from teacher where id=#{id}
</select>

按照结果嵌套查询

<!--根据结果嵌套查询-->
<select id="getStudent2" resultMap="StudentTeacher2">
    select s.id sid,s.name sname,t.name tname from student s,teacher t where s.tid=t.id
</select>
<resultMap id="StudentTeacher2" type="Student">
    <result property="id" column="sid"/>
    <result property="name" column="sname"/>
    <association property="teacher" javaType="Teacher">
        <result property="name" column="tname"/>
    </association>
</resultMap>

回顾Mysql多对一方式

  • 子查询
  • 联表查询

一对多

按照结果查询

<select id="getTeacher" resultMap="StudentTeacher">
    select s.id sid,s.name sname,t.name tname,t.id tid from student s,teacher t where s.tid=t.id and t.id=#{tid}
</select>

<resultMap id="StudentTeacher" type="Teacher">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <collection property="student" ofType="Student" javaType="List">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <result property="tid" column="tid"/>
    </collection>
</resultMap>

动态SQL

1,建表

create table blog(
	id varchar(50) not null comment '博客id',
	title varchar(100) not null comment '博客标题',
	author varchar(30) not null comment '博客作者',
	create_time datetime not null comment '创建时间',
	views int(30) not null comment '浏览量'
)engine=INNODB default charset=utf8;


insert into blog(id,title,author,create_time,views)
values('4','曼巴','kobe','2005-11-11',2952);
insert into blog(id,title,author,create_time,views)
values('3','詹皇','jamas','2002-05-11',2542);

搭建环境,创建一个maven工程

1,导包

2,编写核心配置文件

<?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核心文件-->
<configuration>

    <!--引入外部文件-->
    <properties resource="db.properties"/>

    <!--引入外部配置文件-->
    <settings>
        <!--配置默认日志文件(例如log4j)-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--开启自动驼峰命名规则 就是数据库字段名和实体类字段名不一致create_time转换为createTime-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <!--给实体类起别名-->
    <typeAliases>
        <package name="com.mjn.pojo"/>
    </typeAliases>

    <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>

    <mappers>
        <package name="com.mjn.dao"/>
    </mappers>
</configuration>

3,编写实体类

package com.mjn.pojo;

import java.util.Date;

public class Blog {
    private int id;
    private String title;
    private String author;
    private Date createTime;
    private int views;

    public Blog(int id, String title, String author, Date createTime, int views) {
        this.id=id;
        this.title=title;
        this.author=author;
        this.createTime=createTime;
        this.views=views;
    }

    public Blog() {
    }

    public int getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title=title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author=author;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime=createTime;
    }

    public int getViews() {
        return views;
    }

    public void setViews(int views) {
        this.views=views;
    }

    @Override
    public String toString() {
        return "Blog{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", author='" + author + '\'' +
                ", createTime=" + createTime +
                ", views=" + views +
                '}';
    }
}

4,编写实体类对应Mapper接口和Mapper.xml文件

package com.mjn.dao;

import com.mjn.pojo.Blog;

public interface BlogMapper {
    //插入数据
    int addBlog(Blog blog);
}


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--configuration核心文件-->
<mapper namespace="com.mjn.dao.BlogMapper">
    <insert id="addBlog" parameterType="blog">
        insert into blog(id,title,author,create_time,views)
        values(#{id},#{title},#{author},#{createTime},#{views})
    </insert>

</mapper>

IF

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

Choose

<!--where后第一个where标签会自动拼接到sql语句后面,第二个开始加and-->
<select id="queryBlogChoose" resultType="blog" parameterType="map">
    select * from blog
    <where>
        <choose>
            <when test="title != null">
                and title = #{title}
            </when>
            <when test="author != null">
                and author = #{author}
            </when>
            <otherwise>
                and views = #{views}
            </otherwise>
        </choose>
    </where>
</select>

Set

<update id="updateBlogSet" parameterType="map">
    update blog
    <set>
        <if test="title != null">
            title = #{title},
        </if>
        <if test="author != null">
            author = #{author}
        </if>
    </set>
    where id = #{id}
</update>

trim

  select * from user 

  <trim prefix="WHERE" prefixoverride="AND |OR">
    <if test="name != null and name.length()>0"> AND name=#{name}</if>
    <if test="gender != null and gender.length()>0"> AND gender=#{gender}</if>
  </trim>

解释:

假如说name和gender的值都不为null的话打印的SQL为:select * from user where name = ‘xx’ and gender = ‘xx’

在where后面的(and或or)是不存在第一个and的,上面两个属性的意思如下:

prefix:前缀      
prefixoverride:去掉第一个and或者是or

sql片段

<!--sql片段-->
<sql id="if-title-author">
    <if test="title != null">
        and title = #{title}
    </if>
    <if test="author != null">
        and author=#{author}
    </if>
</sql>

<select id="queryBlogIF" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <include refid="if-title-author"></include>
    </where>
</select>

解释:相当于把增删改查那段重复的判断语句抽取出来,简化代码

最好基于单表定义sql片段

不要存在where标签

Foreach

<!--我们传递的是一个map,在map中可以添加一个集合
    select * from blog where 1=1 and (id=1 or id=2 or id=3)
-->
<select id="queryBlogForeach" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <foreach collection="ids" item="id" open="and (" close=")" separator="or">
            id=#{id}
        </foreach>
    </where>
</select>


@Test
public void queryBlogForeach(){
    SqlSession sqlSession=MybatisUtils.getSqlSession();
    BlogMapper mapper=sqlSession.getMapper(BlogMapper.class);
    HashMap map=new HashMap();

    ArrayList<Integer> ids=new ArrayList<Integer>();
    ids.add(1);

    map.put("ids",ids);
    List<Blog> blogs=mapper.queryBlogForeach(map);

    for (Blog blog : blogs) {
        System.out.println(blog);
    }

    sqlSession.commit();
    sqlSession.close();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值