[Java]Mybatis学习笔记(动力节点老杜)(六)

简介: [Java]Mybatis学习笔记(动力节点老杜)(六)

在 IDEA 中配置 MyBatis 配置文件模版

新建 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>
    <properties resource=""/>
    <typeAliases>
        <package name=""/>
    </typeAliases>
    <environments default="dev">
        <environment id="dev">
            <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>
    </environments>
    <mappers>
        <package name=""/>
    </mappers>
</configuration>

测试使用新建的MyBatis核心配置文件模版

在 IDEA 中配置 SqlMapper 配置文件模版

新建 SqlMapper 配置文件模版

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

测试使用新建的SqlMapper配置文件模版

插入数据时获取自动生成的主键

业务场景说明

  • 存在业务场景,当我们向一张表中插入了一条数据,由于主键一般是自增的,在插入数据时,一般不指定主键,但是此时还有另外一张表,与新插入数据的表有关联关系,该表的外键需要使用新插入的数据的主键值,建立数据之间的关联关系,此时我们就需要获取自动生成的主键值
  • 业务背景:
  • 一个用户有多个角色:插入一个用户数据的同时需要给该用户分配角色:需要将生成的用户的id插入到角色表的user_id字段上
  • 实现方式有两种:
  • 第一种方式:可以先插入用户数据,再写一条查询语句获取新插入用户数据的id,然后再在角色表插入user_id字段。【比较麻烦】
  • 第二种方式:mybatis提供了一种方式更加便捷。

接口声明

/**
 * 插入汽车信息,同时使用生成的主键值
 *
 * @param car 汽车信息
 * @return 影响数据库的条数
 */
int insertCarUseGeneratedKey(Car car);

SQL

<!-- 
  useGeneratedKeys="true" 开启使用自动生成的主键
  keyProperty="id" 指定要将自动生成的主键值保存到用于
           传递数据给SQL语句的对象的哪个属性上
-->
<insert id="insertCarUseGeneratedKey" useGeneratedKeys="true" keyProperty="id">
  insert into t_car 
  values (null, #{carNum}, #{brand}, #{guidePrice}, #{produceTime}, #{carType});
</insert>

测试

@Test
public void testInsertCarUseGeneratedKey() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    Car car = new Car(null, "9199", "凯美瑞", 32.0, "2020-11-12", "电车");
    int count = mapper.insertCarUseGeneratedKey(car);
    System.out.println("影响数据库的条数:" + count);
    System.out.println(car);
    SqlSessionUtil.close();
}

Mybatis 参数处理

  • 数据库表:t_student
USE dbtest;
DROP TABLE IF EXISTS t_student;
CREATE TABLE t_student (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255),
    age INT,
    height DOUBLE,
    birth DATE,
    sex CHAR(1)
);
INSERT INTO t_student(name, age, height, birth, sex) VALUES ('张三', 20, 1.77, '2001-01-02', '男');
INSERT INTO t_student(name, age, height, birth, sex) VALUES ('李四', 20, 1.67, '2001-11-22', '女');
  • 学生类:Student
package cw.study.mybatis.pojo;
import java.util.Date;
/**
 * ClassName: Student
 * Package: cw.study.mybatis.pojo
 * Description:
 *
 * @Author tcw
 * @Create 2023-05-28 11:49
 * @Version 1.0
 */
public class Student {
    private Long id;
    private String name;
    private Integer age;
    private Double height;
    private Character sex;
    private Date birth;
    // constructor
    // setter and getter
    // toString
}

单个简单类型参数

  • 简单类型包括:
  • byte short int long float double char
  • Byte Short Integer Long Float Double Character
  • String
  • java.util.Date
  • java.sql.Date
  • select 标签中有个 parameterType属性:告诉mybatis框架,我这个方法的参数类型是什么类型。
  • 明确指明类型,MyBatis 可以不用进行类型推断,可以提高效率
<!--
  select 标签中有个 parameterType属性
    告诉mybatis框架,我这个方法的参数类型是什么类型。
  mybatis框架自身带有类型自动推断机制,所以大部分情况下parameterType属性都是可以省略不写的。
-->
<select id="selectById" resultType="Student" parameterType="java.lang.Long">
  select * from t_student where id = #{id}
</select>
  • mybatis框架自身带有类型自动推断机制,所以大部分情况下parameterType属性都是可以省略不写的。
SQL语句编译后:select * from t_student where id = ?
JDBC代码是一定要给 ? 传值的,会调用 ps.setXxx(第几个问号, 传什么值);
  ps.setLong(1, 1L);
  ps.setString(1, "zhangsan");
  ps.setDate(1, new Date());
  ps.setInt(1, 100);
  ...
<!-- mybatis框架实际上内置了很多别名,可以参考开发手册 -->
<select id="selectByName" resultType="Student" parameterType="string">
  select * from t_student where name = #{name}
</select>
  • 在#{}中,可以明确告诉mybatis框架,该参数会用什么类型的数据进行填充,对应数据库中的数据类是什么
  • 明确指明类型,MyBatis 可以不用进行类型推断,可以提高效率
<select id="selectByName" resultType="Student" parameterType="string">
  select * from t_student where name = #{name, javaType=String, jdbcType=VARCHAR}
</select>
  • 根据id查询、name查询、birth查询、sex查询
package cw.study.mybatis.mapper;
import cw.study.mybatis.pojo.Student;
import java.util.Date;
import java.util.List;
/**
 * ClassName: StudentMapper
 * Package: cw.study.mybatis.mapper
 * Description:
 *
 * @Author tcw
 * @Create 2023-05-28 11:55
 * @Version 1.0
 */
public interface StudentMapper {
    // 根据id查询
    List<Student> selectById(Long id);
    // name查询
    List<Student> selectByName(String name);
    // birth查询
    List<Student> selectByBirth(Date birth);
    // sex查询
    List<Student> selectBySex(Character sex);
}
<?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="cw.study.mybatis.mapper.StudentMapper">
  <!--
    select 标签中有个 parameterType属性
      告诉mybatis框架,我这个方法的参数类型是什么类型。
    mybatis框架自身带有类型自动推断机制,所以大部分情况下parameterType属性都是可以省略不写的。
  -->
  <select id="selectById" resultType="Student" parameterType="java.lang.Long">
    select * from t_student where id = #{id}
  </select>
  <!-- mybatis框架实际上内置了很多别名,可以参考开发手册 -->
  <select id="selectByName" resultType="Student" parameterType="string">
    select * from t_student where name = #{name, javaType=String, jdbcType=VARCHAR}
  </select>
  <select id="selectByBirth" resultType="Student" parameterType="date">
    select * from t_student where birth = #{birth}
  </select>
  <select id="selectBySex" resultType="Student">
    select * from t_student where sex = #{sex}
  </select>
</mapper>
/**
 * ClassName: StudentMapperTest
 * Package: cw.study.mybatis.test
 * Description:
 *
 * @Author tcw
 * @Create 2023-05-28 11:59
 * @Version 1.0
 */
public class StudentMapperTest {
    @Test
    public void testSelectById() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = mapper.selectById(1L);
        students.forEach(System.out::println);
        SqlSessionUtil.close();
    }
    @Test
    public void testSelectByName() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = mapper.selectByName("李四");
        students.forEach(System.out::println);
        SqlSessionUtil.close();
    }
    @Test
    public void testSelectByBirth() throws ParseException {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        List<Student> students = mapper.selectByBirth(simpleDateFormat.parse("2001-11-22"));
        students.forEach(System.out::println);
        SqlSessionUtil.close();
    }
    @Test
    public void testSelectBySex() {
        SqlSession sqlSession = SqlSessionUtil.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> students = mapper.selectBySex('男');
        students.forEach(System.out::println);
        SqlSessionUtil.close();
    }
}

Map 集合

  • 使用Map集合进行参数的传递,将每个条件以key和value的形式存放到集合中,在使用集合中的数据的时候需要通过#{map集合的key}来取值。
/**
 * 通过集合传递要插入数据库中的学生信息
 * 
 * @param map 学生信息
 * @return 影响数据库的条数
 */
int insertStudentByMap(Map<String, Object> map);
<!--
  parameterType="map" 可以省略, 可以自动推出传入的参数为map集合
  在使用集合中的数据的时候需要通过#{map集合的key}来取值。
-->
<insert id="insertStudentByMap" parameterType="map">
  insert into t_student(id, name, age, sex, height, birth)
  values (null, #{name}, #{age}, #{sex}, #{height}, #{birth});
</insert>
@Test
public void testInsertStudentByMap() {
    // 封装数据
    HashMap<String, Object> map = new HashMap<>();
    // name, age, sex, height, birth
    map.put("name", "张三");
    map.put("age", 20);
    map.put("sex", '男');
    map.put("height", 1.80);
    map.put("birth", new Date());
    SqlSession sqlSession = SqlSessionUtil.openSession();
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    int count = mapper.insertStudentByMap(map);
    System.out.println(count);
    sqlSession.commit();
    SqlSessionUtil.close();
}

实体类 POJO

  • 使用实体类pojo进行参数的传递,将数据封装到实体类中,在使用实体类中的数据的时候需要通过#{get方法去掉get首字母小写}来取值。
/**
 * 通过实体类传递要插入数据库的学生信息
 * 
 * @param student 学生信息
 * @return 影响数据库记录的条数
 */
int insertStudentByPojo(Student student);
<!--
  parameterType="student" 可以省略,可以自动推出类型为Student类
    可以使用 student 是因为在MyBatis核心配置文件中配置了别名
  在使用集合中的数据的时候需要通过#{get方法去掉get首字母小写}来取值。
-->
<insert id="insertStudentByPojo" parameterType="student">
  insert into t_student(id, `name`, age, sex, height, birth)
  values (null, #{name}, #{age}, #{sex}, #{height}, #{birth});
</insert>
@Test
public void testInsertStudentByPojo() {
  // 封装数据
    Student student = new Student(null, "李四", 23, 1.78, '男', new Date());
    SqlSession sqlSession = SqlSessionUtil.openSession();
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    int count = mapper.insertStudentByPojo(student);
    System.out.println(count);
    sqlSession.commit();
    SqlSessionUtil.close();
}

多参数

  • 如果是操作数据库的方法的形参列表是多个参数的话,mybatis框架会自动创建一个Map集合。并且Map集合是以这种方式存储参数的:
map.put("arg0", name);
map.put("arg1", sex);
map.put("param1", name);
map.put("param2", sex);
  • 注意:低版本的mybatis中,使用的是:#{0}和#{1},以及#{2}…,使用mybatis3.4.2之前的版本时:要用#{0}和#{1}这种形式。
  • 高版本的mybatis中,使用的是:
// arg 从 0 开始
#{arg0}
#{arg1}
#{arg2}
// param 从 1 开始
#{param1}
#{param2}
#{param3}
  • 对于操作数据库的方法的形参列表是多个参数的情况,在SQL语句中取数据不能直接使用形参的参数名,会报错
/**
 * 根据学生的姓名和性别进行学生信息的查询
 * 
 * @param name 学生的姓名
 * @param sex 学生的性别
 * @return 学生信息组成的集合
 */
List<Student> selectByNameAndSex(String name, Character sex);
<!-- parameterType="" 不用写了 -->
<select id="selectByNameAndSex" resultType="student">
  select * from t_student
  where `name` = #{arg0} and sex = #{param2};
</select>
@Test
public void testSelectByNameAndSex() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    List<Student> students = mapper.selectByNameAndSex("张三", '男');
    students.forEach(System.out::println);
    SqlSessionUtil.close();
}

@Param(命名参数)

  • 对于操作数据库的方法中形参列表的参数为多个的情况,如果使用arg0 arg1 param1 param2这种方式的话,代码的可读性太差。
  • 在MyBatis中,为我们提供了@Param注解,使我们可以不用arg0 arg1 param1 param2,@Param注解使我们可以自定义存放参数的map集合的key,可以增强代码的可读性。

@Param 的使用

/**
 * 根据学生的姓名和性别进行学生信息的查询
 *
 * @param name 学生的姓名
 * @param sex 学生的性别
 * @return 学生信息组成的集合
 */
List<Student> selectByNameAndSexAnnotation(
        // 使用@Param注解指定参数在map集合中的key
      // @Param注解中的value属性用于指定参数在map集合中的key
        @Param("name") String name, 
        @Param("sex") Character sex
);
  • 使用Param注解后,mybatis框架底层的实现原理:
map.put("name", name);
map.put("sex", sex);
<select id="selectByNameAndSexAnnotation" resultType="student">
  select * from t_student
  where `name` = #{name} and sex = #{sex};
</select>
@Test
public void testSelectByNameAndSexAnnotation() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    List<Student> students = mapper.selectByNameAndSexAnnotation("张三", '男');
    students.forEach(System.out::println);
    SqlSessionUtil.close();
}

注意点

  • 使用了@Param注解之后,arg0和arg1失效了
<select id="selectByNameAndSexAnnotation" resultType="student">
  select * from t_student
  where `name` = #{arg0} and sex = #{arg1};
</select>

  • 使用了@Param注解之后,param1和param2还可以用
<select id="selectByNameAndSexAnnotation" resultType="student">
  select * from t_student
  where `name` = #{param1} and sex = #{param2};
</select>

@Param源码分析

源码跟踪
// mapper 实际上指向了代理对象
StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
// selectByNameAndSexAnnotation 是代理对象 mapper 的代理方法
// 执行到这时,会调用代理对象mapper的代理方法
List<Student> students = mapper.selectByNameAndSexAnnotation("张三", '男');
  • 调用代理对象mapper的代理方法,就是执行 MapperProxy 的 invoke 方法
// Object proxy:代理对象
// Method method:目标方法 
// Object[] args:目标方法的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
        return Object.class.equals(method.getDeclaringClass()) ? method.invoke(this, args) : this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession);
    } catch (Throwable var5) {
        throw ExceptionUtil.unwrapThrowable(var5);
    }
}
  • 接下来执行 this.cachedInvoker(method).invoke(proxy, method, args, this.sqlSession)
// MapperProxy 内部类 PlainMethodInvoker 的方法
public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
    return this.mapperMethod.execute(sqlSession, args);
}
  • 执行 MapperMethod 的 execute 方法进行 SQL 语句类和代理目标方法返回值类型的匹配
// MapperMethod 的方法
public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    Object param;
    // this.command.getType() 获取 SQL 语句的类型(insert|update|select|delete)
    switch (this.command.getType()) {
        case INSERT:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
            break;
        case UPDATE:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
            break;
        case DELETE:
            param = this.method.convertArgsToSqlCommandParam(args);
            result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
            break;
        case SELECT:
            // this.method.returnsVoid() 我们定义的Mapper接口中的方法无返回值
            if (this.method.returnsVoid() && this.method.hasResultHandler()) {
                this.executeWithResultHandler(sqlSession, args);
                result = null;
                // 我们定义的Mapper接口中的方法返回多条记录
            } else if (this.method.returnsMany()) {
                result = this.executeForMany(sqlSession, args);
            } else if (this.method.returnsMap()) {
                result = this.executeForMap(sqlSession, args);
            } else if (this.method.returnsCursor()) {
                result = this.executeForCursor(sqlSession, args);
            } else {
                param = this.method.convertArgsToSqlCommandParam(args);
                result = sqlSession.selectOne(this.command.getName(), param);
                if (this.method.returnsOptional() && (result == null || !this.method.getReturnType().equals(result.getClass()))) {
                    result = Optional.ofNullable(result);
                }
            }
            break;
        case FLUSH:
            result = sqlSession.flushStatements();
            break;
        default:
            throw new BindingException("Unknown execution method for: " + this.command.getName());
    }
    if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
        throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
    } else {
        return result;
    }
}
  • SQL 语句的类型以及返回结果的类型匹配完成后,进行Mapper接口代理方法的执行
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
    // 将Mapper接口参数组成的数组转换为SQL语句中占位符填充的参数
    // 转换成 param1 = value1 param2 = value2 ... 的形式
    // 或者 arg1 = value1 arg2 = value2 ... 的形式
    // 或者 'name' = value1 'sex' = value2 ... 的形式
    Object param = this.method.convertArgsToSqlCommandParam(args);
    List result;
    if (this.method.hasRowBounds()) {
        RowBounds rowBounds = this.method.extractRowBounds(args);
        result = sqlSession.selectList(this.command.getName(), param, rowBounds);
    } else {
        result = sqlSession.selectList(this.command.getName(), param);
    }
    if (!this.method.getReturnType().isAssignableFrom(result.getClass())) {
        return this.method.getReturnType().isArray() ? this.convertToArray(result) : this.convertToDeclaredCollection(sqlSession.getConfiguration(), result);
    } else {
        return result;
    }
}
public Object convertArgsToSqlCommandParam(Object[] args) {
    return this.paramNameResolver.getNamedParams(args);
}
  • 调用 ParamNameResolver 类的 getNamedParams(args) 方法进行转换
public Object getNamedParams(Object[] args) {
    // private final SortedMap<Integer, String> names;
    // 是一个Map集合,key为第几个参数,value为参数对应的名字
    int paramCount = this.names.size();
    if (args != null && paramCount != 0) {
        // 判断方法参数上是否有Param注解
        if (!this.hasParamAnnotation && paramCount == 1) {
            Object value = args[(Integer)this.names.firstKey()];
            return wrapToMapIfCollection(value, this.useActualParamName ? (String)this.names.get(0) : null);
        } else { // 有Param注解走该分支
            // 有Param注解会新建一个Map集合 param集合
            Map<String, Object> param = new MapperMethod.ParamMap();
            int i = 0;
          // 遍历存储参数名字的Map集合
            for(Iterator var5 = this.names.entrySet().iterator(); var5.hasNext(); ++i) {
                Map.Entry<Integer, String> entry = (Map.Entry)var5.next();
                // 向param集合中添加数据,key为接口方法参数的名字 entry.getValue()
                // value为接口方法参数的参数值 args[(Integer)entry.getKey()]
                param.put(entry.getValue(), args[(Integer)entry.getKey()]);
                // genericParamName 通用参数名
                String genericParamName = "param" + (i + 1); // param1 param2 ...
                // 集合是否包含通用参数名 param1 param2 ...
                if (!this.names.containsValue(genericParamName)) {
                    // 这个就是可以使用 param1 param2 获取参数值
                    // 向集合中添加 param1=value1 param2=value2
                    param.put(genericParamName, args[(Integer)entry.getKey()]);
                }
            }
            return param;
        }
    } else {
        return null;
    }
}
图示分析

MyBatis查询语句专题

返回 POJO(一条记录)

public interface CarMapper {
    /**
     * 根据id查询汽车信息
     * 
     * @param id 汽车信息的id
     * @return 汽车信息
     */
    Car selectById(Long id);
}
<!-- 
  如果SQL语句中不使用别名,
  则读取数据后字段名与对象的属性名不一致的话
  不一致的属性的值会为null
-->
<select id="selectById" resultType="car">
  select id,
         car_num      as carNum,
         brand,
         guide_price  as guidePrice,
         produce_time as produceTime,
         car_type     as carType
  from t_car
  where id = #{id};
</select>
@org.junit.Test
public void testSelectById() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    Car car = mapper.selectById(5L);
    System.out.println(car);
    SqlSessionUtil.close();
}

  • 如果返回的结果集可能有多条记录,则不能使用一个pojo对象进行接收,否则会报TooManyResultsException,返回的结果集可能有多条数据记录,则需要使用集合进行接收
目录
打赏
0
0
0
0
17
分享
相关文章
# 【Java全栈学习笔记-U1-day02】变量+数据类型+运算符
本篇笔记主要围绕Java全栈学习的第二天内容展开,涵盖了变量、数据类型、运算符以及Scanner类的应用。首先介绍了变量的概念与命名规范,以及如何定义和使用变量;接着详细讲解了Java中的基本数据类型,包括整型、浮点型、字符型、布尔型等,并通过实例演示了数据类型的运用。随后,深入探讨了各类运算符(赋值、算术、关系、逻辑)及其优先级,帮助理解表达式的构成。最后,介绍了如何利用Scanner类实现用户输入功能,并通过多个综合示例(如计算圆面积、购物打折、变量交换及银行利息计算)巩固所学知识。完成相关作业将进一步加深对这些基础概念的理解与实践能力。
23 12
【Java全栈学习笔记-U1-day01】Java介绍
本笔记整理了Java学习的基础内容,涵盖程序理解、Java语言特性、JDK安装与配置、Java程序开发工具及编写步骤。重点介绍了Java程序的基本结构、编译和运行过程,以及输出语句的使用。通过实例演示了IDEA创建Java程序的方法,并强调了编码规范和注意事项。适合初学者复习和交流学习。 主要内容: 1. 理解程序:计算机组成、程序定义。 2. 简介:Java语言特点、技术平台、JDK作用。 3. 编写Java程序:编写、编译、运行步骤,基本结构。 4. 输出语句 5. DEA使用:新建工程、保存位置、文件介绍、新建类。 6. 扩展:注释、代码规范、大小写敏感、缩进等。
Java使用MyBatis-Plus的OR
通过MyBatis-Plus的条件构造器,Java开发者可以方便地进行复杂的查询条件组合,包括AND和OR条件的灵活使用。熟练掌握这些技巧,可以显著提升开发效率和代码可读性。
97 20
【潜意识Java】MyBatis中的动态SQL灵活、高效的数据库查询以及深度总结
本文详细介绍了MyBatis中的动态SQL功能,涵盖其背景、应用场景及实现方式。
207 6
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
114 2
【潜意识Java】深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
深入理解MyBatis的Mapper层,以及让数据访问更高效的详细分析
139 1
【潜意识Java】深入理解MyBatis,从基础到高级的深度细节应用
本文详细介绍了MyBatis,一个轻量级的Java持久化框架。内容涵盖MyBatis的基本概念、配置与环境搭建、基础操作(如创建实体类、Mapper接口及映射文件)以及CRUD操作的实现。此外,还深入探讨了高级特性,包括动态SQL和缓存机制。通过代码示例,帮助开发者更好地掌握MyBatis的使用技巧,提升数据库操作效率。总结部分强调了MyBatis的优势及其在实际开发中的应用价值。
46 1
Java MyBatis 面试题
Java MyBatis相关基础面试题
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
254 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
ODPS MR节点跑graph连通分量计算代码报错java heap space如何解决
任务启动命令:jar -resources odps-graph-connect-family-2.0-SNAPSHOT.jar -classpath ./odps-graph-connect-family-2.0-SNAPSHOT.jar ConnectFamily 若是设置参数该如何设置