04、Mybatis的CRUD操作

本文详细介绍了MyBatis框架下的基本CRUD操作,包括模糊查询的推荐与不推荐写法,新增用户时获取ID的方法,使用实体类包装对象进行查询,以及结果集的封装技巧。此外,还探讨了如何解决列名与实体类属性不一致的问题。

目录

1-1、like模糊查询占位符:不推荐写法'%${value}%'

1-2、like模糊查询:#{username}推荐写法

2、获取保存数据的id(即新增用户id的返回值)

3、使用实体类的包装对象作为查询条件

5、源码:day02_eesy_01mybatisCRUD

6、Mybatis的CRUD操作


com/itheima/dao/IUserDao.xml

1-1、like模糊查询占位符:不推荐写法'%${value}%'

模糊查询的匹配符%写到配置文件时,用到一个固定写法${value};

源码中指定了读取的key的名字就是value,所以在绑定参数时,只能叫value的名字;

<!--依据住址模糊查询用户('%${value}%'不推荐写法)-->
<select id="findByAddress" resultType="com.itheima.domain.User">
    select * from user where address like '%${value}%'
</select>    
@Test
// 测试依据住址模糊查询用户(不推荐写法)
public void testFindByAddress(){
    // 执行依据住址模糊查询用户方法
    List<User> users = userDao.findByAddress("1区");
    for(User u : users){
        System.out.println(u);
    }
}

执行结果:Statement对象的字符串拼接SQL

 

1-2、like模糊查询:#{username}推荐写法

<!--依据姓名模糊查询用户(#{username}推荐写法)-->
<select id="findByUserName" parameterType="string" resultType="com.itheima.domain.User">
    select * from user where username  like #{username}
</select>
@Test
// 测试依据姓名模糊查询用户
public void testFindByUserName(){
    // 5、执行依据姓名模糊查询用户方法
    List<User> users = userDao.findByUserName("%大王%");
    for(User u : users){
        System.out.println(u);
    }
}

执行结果:PrepareStatement的参数占位符

 

2、获取保存数据的id(即新增用户id的返回值

新增用户后,同时要返回当前新增用户的id值,因为id是由数据库的自动增长来实现的,所以就相当于要在新增后将自动增长auto_increment的值返回。

select last_insert_id()将插入数据的主键返回到 object 对象中,得到刚 insert 进去记录的主键值,只适用与自增主键;

如果insert into user(id)values ("55")中,自己写主键的值,执行select last_insert_id(),获取到的主键值是0;

SQL执行语句:

insert into `mybatis`.`user` (`username`, `birthday`, `sex`, `address`) values ('老王', '2020-02-27 17:47:08', '男', '上海市嘉定区');
select last_insert_id();

com/itheima/dao/IUserDao.xml 

<!--保存用户-->
<insert id="saveUser" parameterType="com.itheima.domain.User">
<!--配置插入操作后,获取插入数据的id-->
<!--keyProperty代表要返回的值名称,keyColumn代表数据库列名,order取值为AFTER代表插入后的行为,resultType代表返回值的类型-->
<selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
    select last_insert_id();
</selectKey>
    insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
</insert>
@Test
// 测试保存用户
public void testSaveUser(){
    User user = new User();
    user.setUsername("小天王");
    user.setSex("女");
    user.setBirthday(new Date());
    user.setAddress("上海市静安区");

    System.out.println("测试保存操作之前:" + user);
    // 5、执行保存用户方法
    userDao.saveUser(user);
    System.out.println("测试保存操作之后:" + user);
}

 执行结果:

 

3、使用实体类的包装对象作为查询条件

mybatis的参数

  • parameterType 输入类型
  • 传递简单类型,如int,string等;
  • 传递pojo对象,如com.itheima.domain.User,mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称;
  • 传递pojo包装对象,开发中,通过pojo传递查询条件,查询条件是综合的查询条件,不仅包括用户查询条件,还包括其他的查询条件(如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数,Pojo类中包含pojo;

 

OGNL表达式:Object Graphic Navigation Language 对象 图 导航 语言

  • 它是通过对象的取值方法来获取数据,在写法上把get给省略了,如getId(),省略了get 

如我们获取用户的名称

  • 类中的写法:user.getUsername();
  • OGNL表达式写法:user.username

mybatis中为什么能直接写username,而不用user.呢?

  • 因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名;

 

需求:根据用户名查询用户信息,查询条件放到QueryVo的user属性中;

自己自定义了一个综合查询条件对象QueryVo,里面包含用户pojo user,也可以包含其他的信息;

将查询条件对象QueryVo作为一个参数传递进去

com.itheima.domain.QueryVo

package com.itheima.domain;

/**
 * @author nikey
 * @date 2020/3/20
 *  把实体类再包装一层,由多个对象组成一个查询条件,实现数据的查询
 */
public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

com.itheima.dao.IUserDao

// 根据queryVo中的条件查询用户
List<User> findUserByVo(QueryVo queryVo);

com/itheima/dao/IUserDao.xml

<!--根据queryVo中的条件查询用户,实体类包装起来做查询-->
<select id="findUserByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User">
    <!--user是QueryVo对象中的属性,要用user.username-->
    select * from user where username like #{user.username}
</select>
@Test
// 测试根据queryVo中的条件查询用户
public void testQueryVo(){
    // 5、执行根据queryVo中的条件查询用户方法
    QueryVo vo = new QueryVo();
    User user = new User();
    user.setUsername("%小%");
    vo.setUser(user);

    List<User> users = userDao.findUserByVo(vo);
    for(User u : users){
        System.out.println(u);
    }
}

 

4、mybatis的输出结果封装

  • resultType 输出类型
  • 输出简单类型,如resultType="int",resultType="string"
  • 输出pojo对象,如resultType="com.itheima.domain.User"
  • 输出pojo列表

 

  • resultType可以指定pojo,将查询结果映射为pojo,但需要pojo的属性名sql查询的列名一致,才可映射成功;
  • 如果sql查询字段名和pojo的属性名不一致,可通过resultMap将字段名和属性名作一个对应关系,resultMap实质上,还需要将查询结果映射到pojo对象中;
  • resultMap可以实现查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list,实现一对一查询和一对多查询;

需求:如果返回的列名和实体类的属性不一致时,就不能封装结果集到指定的实体对象

实现方法有2种:

mysql数据库在windows系统下,不区分大小写,列名是username,实体类属性是userName,实体类属性可以映射到返回的内容;

linux操作系统,严格区分大小写的,username封装不到userName中;

1)SQL语句中,给列名起别名,可以返回的列名和实体类的属性不一致问题;在sql语句层面上解决了问题;

com/itheima/dao/IUserDao2.xml

<select id="findAll" resultType="com.itheima.domain.User2">
    select id as userId, username as userName,birthday as userBirthday, sex as userSex, address as userAddress from user
</select>
package com.itheima.domain;

import java.io.Serializable;
import java.util.Date;

/**
 * @author nikey
 * @date 2020/3/19
 */
public class User2 implements Serializable {
    //  User实例类属性要与数据库user表中的列名一样
    private Integer userId;
    private String userName;
    private Date userBirthday;
    private String userSex;
    private String userAddress;

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Date getUserBirthday() {
        return userBirthday;
    }

    public void setUserBirthday(Date userBirthday) {
        this.userBirthday = userBirthday;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    @Override
    public String toString() {
        return "User2{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", userBirthday=" + userBirthday +
                ", userSex='" + userSex + '\'' +
                ", userAddress='" + userAddress + '\'' +
                '}';
    }
}

 

2)采用配置的方式,配置查询结果的列名实体类的属性名的对应关系

com/itheima/dao/IUserDao2.xml

<!--返回的列名和实体类的属性不一致-->
<mapper namespace="com.itheima.dao.IUserDao2">
    <!--采用配置的方式,配置查询结果的列名和实体类的属性名的对应关系-->
    <!--id是唯一标志,type表示查询的实体类是哪一个实体类类型-->
    <resultMap id="userMap" type="com.itheima.domain.User2">
        <!--主键字段的对应-->
        <id property="userId" column="id" />
        <!--非主键字段的对应-->
        <result property="userAddress" column="address"/>
        <result property="userBirthday" column="birthday"/>
        <result property="userName" column="username"/>
        <result property="userSex" column="sex"/>
    </resultMap>

    <!--依据用户id查询用户信息-->
    <select id="findById" parameterType="integer" resultMap="userMap" >
        select * from user where id = #{userId}
    </select>
</mapper>
  • 第一种方法,执行效率快,SQL语句起别名,开发改造量比较大;
  • 第二种方法,开发效率快,只需要配置一个查询结果的列名和实体类的属性名的对应关系<resultMap>,所有的查询操作,都可以改造成resultMap="userMap";

 

5、源码:day02_eesy_01mybatisCRUD

 

6、Mybatis的CRUD操作

com.itheima.dao.IUserDao

package com.itheima.dao;

import com.itheima.domain.QueryVo;
import com.itheima.domain.User;
import java.util.List;

/**
 * @author nikey
 * @date 2020/3/19
 * 用户的持久层接口
 */
public interface IUserDao {
    // 查询所有操作
    List<User> findAll();

    // 依据用户id查询用户信息
    User findById(Integer id);

    // 依据姓名模糊查询用户
    List<User> findByUserName(String username);

    // 依据住址模糊查询用户
    List<User> findByAddress(String address);

    // 查询总用户数
    int findTotal();

    // 根据queryVo中的条件查询用户
    List<User> findUserByVo(QueryVo queryVo);

    // 保存用户操作
    void saveUser(User user);

    // 更新用户操作
    void updateUser(User user);

    // 删除用户操作
    void deleteUser(Integer id);
}

com.itheima.domain.User

package com.itheima.domain;

import java.io.Serializable;
import java.util.Date;

/**
 * @author nikey
 * @date 2020/3/19
 */
public class User implements Serializable {
    //  User实例类属性要与数据库user表中的列名一样
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;


    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday='" + birthday + '\'' +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}

com.itheima.domain.QueryVo

package com.itheima.domain;

/**
 * @author nikey
 * @date 2020/3/20
 *  把实体类再包装一层,由多个对象组成一个查询条件,实现数据的查询
 */
public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

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.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://192.168.171.131:3306/mybatis?characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <!-- 配置映射文件的位置,映射配置文件指每个dao独立的配置文件 -->
        <mapper resource="com/itheima/dao/IUserDao.xml"/>
    </mappers>
</configuration>

com/itheima/dao/IUserDao.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">

<!-- 命名空间,xml文件和dao接口对接起来 -->
<!--dao的全限定类名-->
<mapper namespace="com.itheima.dao.IUserDao">
    <select id="findAll" resultType="com.itheima.domain.User">
        select * from user
    </select>

    <!--保存用户-->
    <insert id="saveUser" parameterType="com.itheima.domain.User">
    <!--配置插入操作后,获取插入数据的id-->
    <!--keyProperty代表要返回的值名称,keyColumn代表数据库列名,order取值为AFTER代表插入后的行为,resultType代表返回值的类型-->
    <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
        select last_insert_id();
    </selectKey>
        insert into user(username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})
    </insert>

<!--更新用户-->
    <update id="updateUser" parameterType="com.itheima.domain.User">
        update user set username=#{username},birthday=#{birthday},sex=#{sex},address=#{address} where id = #{id}
    </update>

    <!--删除用户-->
    <delete id="deleteUser" parameterType="integer">
        delete from user where id = #{id}
    </delete>

    <!--依据用户id查询用户信息-->
    <select id="findById" parameterType="integer" resultType="com.itheima.domain.User" >
        select * from user where id = #{id}
    </select>

    <!--依据姓名模糊查询用户(#{username}推荐写法)-->
    <select id="findByUserName" parameterType="string" resultType="com.itheima.domain.User">
        select * from user where username  like #{username}
    </select>

    <!--查询总用户数-->
    <select id="findTotal" resultType="int">
        select count(*) from user
    </select>

    <!--依据住址模糊查询用户('%${value}%'不推荐写法)-->
    <select id="findByAddress" resultType="com.itheima.domain.User">
        select * from user where address like '%${value}%'
    </select>

    <!--根据queryVo中的条件查询用户,实体类包装起来做查询-->
    <select id="findUserByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User">
        <!--user是QueryVo对象中的属性,要用user.username-->
        select * from user where username like #{user.username}
    </select>
</mapper>

com.itheima.test.MybatisTest

package com.itheima.test;

import com.itheima.dao.IUserDao;
import com.itheima.domain.QueryVo;
import com.itheima.domain.User;
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.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;

/**
 * @author nikey
 * @date 2020/3/19
 */
public class MybatisTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession session;
    private IUserDao userDao;

    @Before  // 用于在测试方法执行之前执行
    public void init() throws IOException {
        // 1、读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        // 2、获取SqlSessionFactory
        factory = new SqlSessionFactoryBuilder().build(in);
        // 3、获取SqlSession对象
        session = factory.openSession();
        // 4、获取Dao的代理对象
        userDao = session.getMapper(IUserDao.class);
    }

    @After  // 用于在测试方法执行之后执行
    public void destroy() throws IOException {
        // 提交事务
        session.commit();

        // 释放资源
        session.close();
        in.close();
    }

    @Test
    // 测试查询所有用户
    public void testFindAll(){
        // 5、执行查询所有方法
        List<User> users = userDao.findAll();
        for(User u : users){
            System.out.println(u);
        }
    }

    @Test
    // 测试保存用户
    public void testSaveUser(){
        User user = new User();
        user.setUsername("小天王");
        user.setSex("女");
        user.setBirthday(new Date());
        user.setAddress("上海市静安区");

        System.out.println("测试保存操作之前:" + user);
        // 5、执行保存用户方法
        userDao.saveUser(user);
        System.out.println("测试保存操作之后:" + user);
    }

    @Test
    // 测试更新用户
    public void testUpdateUser(){
        User user = new User();
        user.setId(48);
        user.setUsername("我是更新用户48");
        user.setAddress("我家在上海市48区");
        user.setBirthday(new Date());
        user.setSex("女");

        // 5、执行更新用户方法
        userDao.updateUser(user);
        User u = userDao.findById(48);
        System.out.println(u);
    }

    @Test
    // 测试删除用户
    public void testDeleteUser(){
        // 5、执行删除用户方法
        userDao.deleteUser(49);
        System.out.println("删除用户成功.......");
    }

    @Test
    // 测试依据用户id查询用户信息
    public void testFindById(){
        // 5、执行依据用户id查询用户信息方法
        User user = userDao.findById(45);
        System.out.println(user);
    }

    @Test
    // 测试依据姓名模糊查询用户
    public void testFindByUserName(){
        // 5、执行依据姓名模糊查询用户方法
        List<User> users = userDao.findByUserName("%大王%");
        for(User u : users){
            System.out.println(u);
        }
    }

    @Test
    // 测试查询总用户数
    public void testFindTotal(){
        // 5、执行查询总用户数方法
        int total = userDao.findTotal();
        System.out.println(total);
    }

    @Test
    // 测试依据住址模糊查询用户(不推荐写法)
    public void testFindByAddress(){
        // 执行依据住址模糊查询用户方法
        List<User> users = userDao.findByAddress("1区");
        for(User u : users){
            System.out.println(u);
        }
    }

    @Test
    // 测试根据queryVo中的条件查询用户
    public void testQueryVo(){
        // 5、执行根据queryVo中的条件查询用户方法
        QueryVo vo = new QueryVo();
        User user = new User();
        user.setUsername("%小%");
        vo.setUser(user);

        List<User> users = userDao.findUserByVo(vo);
        for(User u : users){
            System.out.println(u);
        }
    }
}

day02_eesy_01mybatisCRUD/pom.xml

<?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.itheima</groupId>
    <artifactId>day02_eesy_01mybatisCRUD</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
    <!--mybatis-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.6</version>
    </dependency>

    <!--日志-->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.12</version>
    </dependency>

    <!--单元测试-->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.10</version>
    </dependency>

</dependencies>
</project>

 

【完美复现】面向配电网韧性提升的移动储能预布局与动态调度策略【IEEE33节点】(Matlab代码实现)内容概要:本文介绍了基于IEEE33节点的配电网韧性提升方法,重点研究了移动储能系统的预布局与动态调度策略。通过Matlab代码实现,提出了一种结合预配置和动态调度的两阶段优化模型,旨在应对电网故障或极端事件时快速恢复供电能力。文中采用了多种智能优化算法(如PSO、MPSO、TACPSO、SOA、GA等)进行对比分析,验证所提策略的有效性和优越性。研究不仅关注移动储能单元的初始部署位置,还深入探讨其在故障发生后的动态路径规划与电力支援过程,从而全面提升配电网的韧性水平。; 适合人群:具备电力系统基础知识和Matlab编程能力的研究生、科研人员及从事智能电网、能源系统优化等相关领域的工程技术人员。; 使用场景及目标:①用于科研复现,特别是IEEE顶刊或SCI一区论文中关于配电网韧性、应急电源调度的研究;②支撑电力系统在灾害或故障条件下的恢复力优化设计,提升实际电网应对突发事件的能力;③为移动储能系统在智能配电网中的应用提供理论依据和技术支持。; 阅读建议:建议读者结合提供的Matlab代码逐模块分析,重点关注目标函数建模、约束条件设置以及智能算法的实现细节。同时推荐参考文中提及的MPS预配置与动态调度上下两部分,系统掌握完整的技术路线,并可通过替换不同算法或测试系统进一步拓展研究。
先看效果: https://pan.quark.cn/s/3756295eddc9 在C#软件开发过程中,DateTimePicker组件被视为一种常见且关键的构成部分,它为用户提供了图形化的途径来选取日期与时间。 此类控件多应用于需要用户输入日期或时间数据的场景,例如日程管理、订单管理或时间记录等情境。 针对这一主题,我们将细致研究DateTimePicker的操作方法、具备的功能以及相关的C#编程理念。 DateTimePicker控件是由.NET Framework所支持的一种界面组件,适用于在Windows Forms应用程序中部署。 在构建阶段,程序员能够通过调整属性来设定其视觉形态及运作模式,诸如设定日期的显示格式、是否展现时间选项、预设的初始值等。 在执行阶段,用户能够通过点击日历图标的下拉列表来选定日期,或是在文本区域直接键入日期信息,随后按下Tab键或回车键以确认所选定的内容。 在C#语言中,DateTime结构是处理日期与时间数据的核心,而DateTimePicker控件的值则表现为DateTime类型的实例。 用户能够借助`Value`属性来读取或设定用户所选择的日期与时间。 例如,以下代码片段展示了如何为DateTimePicker设定初始的日期值:```csharpDateTimePicker dateTimePicker = new DateTimePicker();dateTimePicker.Value = DateTime.Now;```再者,DateTimePicker控件还内置了事件响应机制,比如`ValueChanged`事件,当用户修改日期或时间时会自动激活。 开发者可以注册该事件以执行特定的功能,例如进行输入验证或更新关联的数据:``...
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值