Mybatis

目录

快速入门

配置SQL提示

JDBC 

数据库连接池 

lombok 

基础操作

删除

日志输出 

​编辑 SQL注入

新增

主键返回 

修改

查询 

根据Id查询

数据封装

条件查询 

concat字符串拼接函数 

​编辑

XML映射文件 

动态SQL


是一种优秀的持久层框架,用于简化JDBC的开发

快速入门

利用mybatis查询表中的所有信息

1.创建Spring工程,引入mybatis依赖(在sql中选择Mybatis Famework和Mysql driver)

2.根据表格创建实体类

public class User {
    private Integer id;
    private String name;
    private Short age;
    private Short gender;
    private String phone;

    public User(Integer id, String name, Short age, Short gender, String phone) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.phone = phone;
    }

    public User() {
    }

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Short getAge() {
        return age;
    }

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

    public Short getGender() {
        return gender;
    }

    public void setGender(Short gender) {
        this.gender = gender;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", gender=" + gender +
                ", phone='" + phone + '\'' +
                '}';
    }
}

3.在application.properties中配置数据库四要素

#配置数据库的连接信息
#驱动类名称

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=123456

4.定义UserMapper,编写SQL语句

//运行时,会自动生成该接口的实现类对象(代理对象),并且将该对象交给IOC容器处理
@Mapper
public interface UserMapper {
    //查询全部用户信息
    @Select("select * from user")
    public List<User> list();
}

5.在test中编写测试代码

@SpringBootTest
//Springboot整合单元测试的注解
class Mybatis1ApplicationTests {
    //由于接口不能直接创建对象,但是他会创建代理对象
    @Autowired
    private UserMapper userMapper;
@Test
public void testListUser(){
    List<User> userList=userMapper.list();
    userList.stream().forEach(user->{
        System.out.println(user);
    });
}
}

配置SQL提示

配置之后写错会有提示,会方便很多

在写user的时候没有提示或者直接爆红的话,就要配置idea中Mysql数据库的连接

JDBC 

在idea里面对数据库内容进行更改

是sun公司定义的一套操作所有关系型数据库的规则,即接口

各个数据库提供jar包

真正执行的代码是驱动jar包中的实现类

优点:可以通过这个对所有数据库进行操作

可以随时替换底层数据库,访问的java代码不改变

代码实例

public class qwwe {
    public static void main(String[] args) throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //上面这个写不写都行,因为驱动包里面就已经带着有了
        //2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/db1";
        String username = "root";
        String password = "1040272215Aa";

        Connection connection = DriverManager.getConnection(url,username,password);


        //3.定义sql
        String sql = "update new1 set salary = 10000 where id = 2 ";

        //4.获取sql的对象Statement
        Statement statement = connection.createStatement();

        //5.执行sql
        int count = statement.executeUpdate(sql);

        //6.处理结果
        System.out.println(count);

        //7.释放资源
        statement.close();
        connection.close();
    }
}

数据库连接池 

数据库连接池是一个容器,负责分配管理数据库连接

它允许应用程序重复使用一个现有的数据库连接,而不是重新再建一个

释放空闲时间超过最大空闲时间的连接,将会直接释放,来避免因为没有释放连接而引起的数据库连接遗漏

好处:

资源重新用

提升系统影响速度

避免数据库连接遗漏,就是怕有的用户没有连接可用

image-20240111104503610

image-20240111104731551

Spring中默认的连接池是Hikari,怎么将连接池切换成Durid呢?

lombok 

lambok会在编译的时候,自动生成对应的java代码,我们使用lambok时,还需安装一个lambok插件(idea自带) 

基础操作

删除


@Mapper
public interface EmpMapper {
    //根据ID删除数据
    @Delete("delete from emp where id= #{id}")
    public void delete(Integer id);
}
@SpringBootTest
class SpringBaseApplicationTests {
@Autowired
private EmpMapper empMapper;
@Test
public void testDelete(){
   empMapper.delete(16);

}
    @Test
    void contextLoads() {
    }
}

删除一般不需要返回值,如果要返回值的话,可以将代码做如下修改

@Test
public void testDelete(){
   int dele=empMapper.delete(16);
    System.out.println(dele);
}
    //根据ID删除数据
    @Delete("delete from emp where id= #{id}")
    public int delete(Integer id);

这里返回的值是运行以后影响的行数

如果mapper接口方法形参只有一个普通类型的参数,#{}里面的属性名可以随便写,比如#{id} ,    #{value}

日志输出 

如果要看到后台是怎么运行的,那么需要在properties处配置:

#配置mybatis的日志,指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

再次运行,可以在控制台上看到:

第二行和第三行叫做预编译SQL,他的好处是性能更高,更安全(防止SQL注入) 

 SQL注入

是通过操作输入的数据来修改事先预定好的SQL语句,以达到执行代码对服务器进行攻击的方法

 比如这条语句,1=1恒定为true,所以就算密码错误,也能登陆进去

新增

    @Insert("insert into emp (username, name, gender, image, job, entrydate,dept_id,create_time,update_time)"
            +"values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptld},#{createTime},#{updateTime})")
    public void insert (Emp emp);
@Test
public void testInsert(){
    Emp emp=new Emp();
    emp.setUsername("Tom");
    emp.setName("汤姆");
    emp.setImage("1.jpg");
    emp.setGender((short)1);
    emp.setJob((short)1);
    emp.setEntrydate(LocalDate.of(2000,1,1));
    emp.setCreateTime(LocalDateTime.now());
    emp.setUpdateTime(LocalDateTime.now());
    emp.setDeptld(1);
empMapper.insert(emp);
}

由于要输入的数据很多,所以我们这里可以定义一个实体类,直接传递实体类。

values传入的要和定义的实体类的getter和setter方法名字一样,不然会报错。传入的是属性名,而不是字段名

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
    private Integer id;
    private String username;
    private String password;
    private String name;
    private Short gender;
    private String image;
    private Short job;
    private LocalDate entrydate;
    private Integer deptld;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

我出现了这样的情况是我定义的是deptld,但是在传给value的时候名字不一致,就报错了

主键返回 

在数据添加成功后,需要获取插入数据库数据的主键,比如添加套餐数据时,还需要维护套餐菜品关系表数据

默认执行基础操作不会返回主键值

表示返回的主键值是19 

修改

    //更新员工
    @Update("update emp set username=#{username},name=#{name},gender=#{gender},image =#{image},"
    +"job=#{job},entrydate=#{entrydate},dept_id=#{deptld},update_time=#{updateTime} where id =#{id}")
    public void update(Emp emp);
//更新
@Test
public void testUpdate(){
    Emp emp=new Emp();
    emp.setId(18);
    emp.setUsername("Tom2");
    emp.setName("汤姆2");
    emp.setImage("1.jpg");
    emp.setGender((short)1);
    emp.setJob((short)1);
    emp.setEntrydate(LocalDate.of(2000,1,1));
    emp.setUpdateTime(LocalDateTime.now());
    emp.setDeptld(1);
    empMapper.update(emp);
}

查询 

根据Id查询

//根据ID查询员工
    @Select("select * from emp where id = #{id}")
    public Emp getById(Integer id);
//根据ID查询员工
    @Test
    public void testGetById(){
    Emp emp=empMapper.getById(18);
        System.out.println(emp);
    }

可以看到后面三个字段值全部为null,没有封装进来! 

数据封装

实体类属性名和数据库查询返回的字段名一致,mybatis会自动封装

如果实体类属性名和数据库查询返回的字段名不一致,不能自动封装

解决方案:

方案一:给字段起别名 ,让别名与实体类的属性一致

   //方案一:给字段起别名 ,让别名与实体类的属性一致
   @Select("select id, username, password, name, gender, image, job, entrydate, dept_id deptld, create_time createTime, update_time updateTime from emp where id = #{id}")
    public Emp getById(Integer id);

方案二:通过@Results和@Result注解手动映射封装

//方案二:通过@Results和@Result注解手动映射封装
    @Results({
            @Result(column = "dept_id",property ="deptld"),   //前者表示表中的字段名,后者表示类中的属性名
            @Result(column = "create_time",property ="createTime"),
            @Result(column = "update_time",property ="updateTime")
    })
    @Select("select * from emp where id = #{id}")
    public Emp getById(Integer id);

方案三:开启mybatis的驼峰命名自动映射的开关

在properties中配置

mybatis.configuration.map-underscore-to-camel-case=true

结果如图,可以都封装进来了

条件查询 

    //条件查询员工
    @Select("select * from emp where name like '%${name}%' and gender=#{gender} and entrydate between #{begin} and #{end} order by update_time desc ")
    public List<Emp> list(String name, Short gender, LocalDate begin,LocalDate end);
//条件查询
    @Test
    public void testList(){

    List<Emp> emplist=empMapper.list("张",(short)1,LocalDate.of(2010,1,1),LocalDate.of(2020,1,1));
        System.out.println(emplist);
}

在模糊查询中引号里面是一个字符串,但是#{}不能直接在字符串中直接使用,所以用$符号,直接拼接,不会生成预编译语句,此时出现的问题是性能低 ,不完全,存在SQL注入问题

concat字符串拼接函数 

可以用这个解决问题

    @Select("select * from emp where name like concat('%',#{name},'%') and gender=#{gender} and entrydate between #{begin} and #{end} order by update_time desc ")
    public List<Emp> list(String name, Short gender, LocalDate begin,LocalDate end);
}

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="org.example.springbase.mapper.EmpMapper"> <!--这的名字与EmpMapper的全类名保持一致,点击接口名字,右键->copy reference-->

<select id="list" resultType="org.example.springbase.Pojo.Emp"> <!-->id属性与mapper接口方法名一致,后面指的是单条记录所封装的全类名  emp->右键->copy reference-->
select * from emp where name like concat('%',#{name},'%') and gender=#{gender} and entrydate between #{begin} and #{end} order by update_time desc
</select>
</mapper>
 public List<Emp> list(String name, Short gender, LocalDate begin,LocalDate end);

使用mybatis注解,主要是来完成一些简单的增删改查操作,如果需要实现复杂的SQL功能,建议配置XML来配置映射 语句

动态SQL

随着用户的输入或者外部条件的变化而变化的SQL语句,我们称为动态SQL

<if>

用于判断条件是否成立,使用test属性进行条件判断,如果条件为true,则凭借SQL

<?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="org.example.springbase.mapper.EmpMapper"> <!--这的名字与EmpMapper的全类名保持一致,点击接口名字,右键->copy reference-->

    <select id="list"
            resultType="org.example.springbase.Pojo.Emp"> <!-->id属性与mapper接口方法名一致,后面指的是单条记录所封装的全类名  emp->右键->copy reference-->
        select * from emp <where>
                              <if test="name != null">
                              name like concat('%',#{name},'%')
                              </if>
                            <if test="gender!=null">
                            and gender=#{gender}
                            </if>
                            <if test="begin !=null and end !=null">
                            and entrydate between #{begin}and #{end}
                            </if>
        </where>
        order by update_time desc
    </select>
</mapper>
    @Test
    public void testList(){

    List<Emp> emplist=empMapper.list("张",null,null,null);
        System.out.println(emplist);

<where>

<where>标签的两个作用:只会在子元素有内容的情况下才插入where子句(如果都不成立,就不会生成where),而且会自动去除子句的开头的and或者or 

<set>

用于update方法中,动态地在行首插入set关键字,并且会删除额外的逗号

<foreach>

<!--批量删除   delete  from emp where id in (18,19,20)-->
    <!--collection:遍历的集合
    item:遍历出来的元素
    separator:分隔符
    open:遍历开始前拼接的SQL片段
    close:遍历开始后拼接的SQL片段
    -->
    <delete id="deleteByIds">
        delete  from emp where id in
                         <foreach collection="ids" item="id" separator="," open="(" close=")">
                             #{id}
                         </foreach>
    </delete>
    //批量删除员工
    public void deleteByIds(List<Integer> ids);

<sql><include>

如果要查询的字段重复使用,之前的代码存在的问题是复用性差,用这两个标签解决

<sql id="commonSelect">  #名字自己取
    select id,username,password,name,gender,image,job,entrydate,dept_id,create_time,update_time
    from emp
</sql>

<select id="list"
            resultType="org.example.springbase.Pojo.Emp"> <!-->id属性与mapper接口方法名一致,后面指的是单条记录所封装的全类名  emp->右键->copy reference-->
        <include refid="commonSelect"/>
<where>
                              <if test="name != null">
                              name like concat('%',#{name},'%')
                              </if>
                            <if test="gender!=null">
                            and gender=#{gender}
                            </if>
                            <if test="begin !=null and end !=null">
                            and entrydate between #{begin}and #{end}
                            </if>
        </where>
        order by update_time desc
    </select>

    @Test
    public void testList(){

    List<Emp> emplist=empMapper.list("张",null,null,null);
        System.out.println(emplist);
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值