Mybatis3快速上手(详细)

2023-11-14

因为编辑器不互通,所以可以直接打开有道云看
有道云链接


  1. Mybatis的初入
    创建Maven项目工程,因为Mybatis属于数据访问层的操作,我们需要引入相关依赖
    mysql mysql-connector-java 8.0.29 org.mybatis mybatis 3.5.9 junit junit 4.13.2 test org.projectlombok lombok 1.18.24

因为是对于数据库做操作,所以需要有一个对应的数据库。数据库名称为mybatis。在数据库里新建一个表,叫做table_users。
create table table_users(
id int(20) primary key auto_increment,
username varchar(30),
password varchar(30),
age int(10),
gender char,
email varchar(50)
);

在创建好数据库以后,要有一个与之对应的实体类。也就是User类。可以把放置在Pojo包下。User类代码如下。(有lombok)

package mybatis.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {

private Integer id;

private String username;

private String password;

private Integer age;

private String gender;

private String email;

}

创建mybatis的核心配置文件。

一般来说,配置文件分为mapper映射文件,和mybatis的核心配置文件。 mybatis的核心配置文件,用来配置数据库的连接信息,mybatis的全局配置等等。针对于配置文件的命名规范,myabtis并没有什么强制性要求,不过推荐把mybatis的核心配置文件叫做 mybatis-config.xml。一般来说,该文件位于maven项目的 src/resource文件目录下。

Mybatis-config.xml 配置模板

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 映射 -->
<mappers>

</mappers>

在创建好mybatis-config.xml之后,我们需要有一个Mapper接口。

package mybatis.mapper;

public interface UserMapper {

int insertUser();

}

然后我们需要有一个对应Mapper接口的Mapper.xml映射文件。namespace对应的是Mapper接口,id对应的是接口内的方法名称

<?xml version="1.0" encoding="UTF-8" ?>
<insert id="insertUser">
    insert into table_users value (null, 'jack', '123513', 15, '男', '878035748@qq.com')
</insert>

剩下内容均在测试类内完成。

import mybatis.mapper.UserMapper;
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 MybatisTest {

@Test
public void helloMybatis() {

    try {
        // 通过mybatis提供的Resources获取到输入流配置文件。
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");

        // 通过sqlSession工厂来取出会话, openSession设置为true自动提交事务
        SqlSession sqlSession = (SqlSession) new SqlSessionFactoryBuilder().build(resourceAsStream).openSession(true);

        // 动态代理,获取Mapper实现
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        // 执行方法
        System.out.println("执行结果条数为: " + mapper.insertUser());

        // 释放资源
        sqlSession.close();

    } catch (IOException e) {

        e.printStackTrace();

    }

}

}

  1. Mybatis增删改查操作以及抽取工具类
    抽取工具类Util
    package mybatis.uitl;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;

public class SqlSessionUtil {

public static SqlSession getSqlSession() {
    try {
        return new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).openSession(true);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

}

2.1 Mybatis增加操作

UserMapper.class
public interface UserMapper {
int insertUser();
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<insert id="insertUser">
    insert into table_users value (null, 'jack', '123513', 15, '男', '878035748@qq.com')
</insert>

mybatis-config.xml

test测试类
@Test
public void helloMybatis() {

try {
    // 通过mybatis提供的Resources获取到输入流配置文件。
    InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");

    // 通过sqlSession工厂来取出会话, openSession设置为true自动提交事务
    SqlSession sqlSession = (SqlSession) new SqlSessionFactoryBuilder().build(resourceAsStream).openSession(true);

    // 动态代理,获取Mapper实现
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);

    // 执行方法
    System.out.println("执行结果条数为: " + mapper.insertUser());

    // 释放资源
    sqlSession.close();

} catch (IOException e) {

    e.printStackTrace();

}

}

2.2 Mybatis修改操作

UserMapper.class
public interface UserMapper {
void updateUser();
}

UserMapper.xml

update table_users set username = ‘root’, password = ‘123’ where id = 2

test测试类
@Test
public void updateUsers() {

SqlSession sqlSession = SqlSessionUtil.getSqlSession();

assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

mapper.updateUser();

}

2.3 Mybatis删除操作

UserMapper.class
public interface UserMapper{
void deleteUser();
}

UserMapper.xml

delete from table_users where id = 3’

test测试类
@Test
public void deleteUser() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.deleteUser();
}

2.4 Mybatis查询
当表内的字段能和实体类一一对应的时候,查询多条数据,也可以返回值使用该实体类。进行封装。
UserMapper.class
public interface UserMapper {
User getUser();
List getAllUser();
}

UserMapper.xml

select * from users where id = 1

select * from users

test测试代码
@Test
public void selectUser() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
System.out.println(mapper.selectUser());
}

@Test
public void selectAllUser() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
mapper.selectAllUsers().forEach(System.out::println);
}

  1. Mybatis核心配置文件

3.1 Mybatis核心配置文件标签优先级
(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)

3.2 Mybatis核心配置文件之Environments

environments 配置连接数据库的环境。在environments下面,可以有很多个不同的 envrionment。每一个environment都有一个对应的数据库环境。在开发中,不可能同时使用多个数据库环境。所以,在environments中有一个属性。default。可以通过default绑定environment的id与之对应。

在 environment 中,id标识是唯一的,每一个id对应一个数据库操作环境。并且它拥有子标签 TeanscationManager 事务处理器,一般来说,使用JDBC支持的事务开启。采用JDBC原生的事务管理方式。
dataSource 数据源。里面设置数据库链接相关的内容,驱动,url, username, password。 在dataSource中,有一个属性type。这里是选择数据源获取的方式,上面代码选择了池类型。
3.3 在核心配置文件中引入properties文件
如果想把dataSource中的数据源信息抽取出去,改为外部文件配置。解耦。可以采用一个新的标签。 在该标签内,有一个resource属性。对应你需要引入的properties文件。如下

然后在dataSource中,采用 这 种 方 式 , 来 对 数 据 进 行 引 入 。 例 如 , 我 j d b c . p r o p e r t i e s 中 的 一 些 键 值 对 是 这 样 的 j d b c . d r i v e r = c o m . m y s q l . c j . j d b c . D r i v e r j d b c . u s e r n a m e = r o o t j d b c . p a s s w o r d = r o o t j d b c . u r l = j d b c : m y s q l : / / l o c a l h o s t : 3306 / m y b a t i s ? s e r v e r T i m e z o n e = U T C 则 我 在 d a t a S o u r c e 中 采 用 这 种 方 式 引 入 < d a t a S o u r c e t y p e = " P O O L E D " > < ! − − 数 据 库 驱 动 − − > < p r o p e r t y n a m e = " d r i v e r " v a l u e = " {} 这种方式,来对数据进行引入。例如,我jdbc.properties中的一些键值对是这样的 jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.username=root jdbc.password=root jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC 则我在dataSource中采用这种方式引入 <dataSource type="POOLED"> <!-- 数据库驱动 --> <property name="driver" value=" jdbc.propertiesjdbc.driver=com.mysql.cj.jdbc.Driverjdbc.username=rootjdbc.password=rootjdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTCdataSource<dataSourcetype="POOLED"><!><propertyname="driver"value="{jdbc.driver}"/>






3.4 别名配置TypeAliases
在很多时候用全包类名很不方便,比如如下场景。

select * from table_users where id = 2

select * from table_users 可以看到在返回值类型中,采用的是全包类名的样式,此时就可以设置别名来解决繁杂问题。需要注意的是标签和标签之间的对应位置。 这样,就配置好了一个别名,其中,type属性的意义是表示配置的类型,alias属性的意义表示的是别名的名称,在上述配置完成后,意义表达为。我要把mybatis.pojo包下的User类的名字叫做 user。 以后我使用user,就表示的是 mybatis.pojo.User。同样,优化过后的mapper.xml文件就是如下 select * from table_users where id = 2 select * from table_users 还有另外一种情况,只设置type,不设置alias那么他就会默认使用类名,且不区分大小写。如下 3.5 通过包来设置别名 在通过这种package来设置的话,在该包底下所有的内容,都会变成上述类名方式,大小写且不区分。

3.6 Mybatis核心配置文件之Mappers
用来映射Mapper配置文件的位置,有不同的方式,经典的是逐个配置如下。

通过mapper标签,来一个一个配置对应Mpaaer.xml的位置,但是同样他也有包扫描。 但是有两个注意点! 1. Mapper.xml所在的路径必须和Mapper.interface所在的路径一致。 2. Mapper.xml 和对应的接口 Mapper.class 文件名称必须一致。
  1. Mybatis获取参数值
    Mybatis提供了两种获取参数的方式, ${} 的本意是字符串拼接 , #{} 的本意类似于占位符,可以避免sql注入。

4.1 单个字面量类型的参数获取
字面量对应变量。可以理解为单个变量的获取。也就是说 基本数据类型,字符串,对应的包装类型等。
仅仅展示Mapper.xml 和 Test的内容即可理解

select * from table_users where username = #{username}

mapper.getUserByUsername(“root”)

需要注意的是,这里并不打算采用$符号,因为本来就是需要防止sql注入的。并且。在xml中的 {} 内,并不一定是写username,随便写什么都可以,它仅仅是存在占位的作用,但是为了做到见名知意,最好和Interface中的参数一致。

4.2 多个字面量类型的参数获取
同上内容,只不过由一个变成多个。需要注意的是。变成多个后,mybatis会把其封装成Map集合,获取你的参数可以通过键值对的方式来获取,mybatis提供了两种方式。
第一种是: arg0,arg1, arg2, arg3… 第二种是, param1, param2, param3…

接口内代码内容

public interface UserMapper {
User checkLogin(String username, String password);
}
Mapper.xml内容

select * from table_users where username = #{param1} and password = #{param2}

或者如下

select * from table_users where username = #{arg0} and password = #{arg1}

test内容
@Test
public void test2() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

System.out.println(mapper.checkLogin("root", "123"));
// 输出结果
// User(id=2, username=root, password=123, age=15, gender=男, email=878035748@qq.com)

}

4.3 通过Map集合的方式获取多个参数
在4.2中,获取的多个参数并不能自己定义kay值,需要按照mybatis提供的两种key来获取,一个是arg,一个是param。如果想要自定义key,则我们可以自己去写一个Map对象,然后即可使用自己的key来进行获取,不好的一点就是。需要手动进行数据pus。
interface

public interface UserMapper {
User checkLoginByMap(Map<String, Object> map);
}
Mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<select id="checkLoginByMap" resultType="User">
    select * from table_users where username = #{username} and password = #{password}
</select>
test public void test3() {
SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

Map<String, Object> map = new HashMap<>();

map.put("username", "root");
map.put("password", "123");

System.out.println(mapper.checkLoginByMap(map));

}

4.4 获取实体对象内的参数
若有一个实体类,实体类内有成员变量。成员变量和属性并非一个东西。什么是属性呢,把成员变量的对应的Get和Set方法,去掉get和set,剩下的全小写。即为属性名称。比如
有一个id的成员变量的get/set方法为 getId, setId, 则属性名称则是 id。
而Mybatis获取实体对象内的参数是通过属性名称来获取的。代码如下。
interface
void insertUser(User user);
Mapper.xml

insert into table_users values(null, #{username}, #{password}, #{age}, #{gender}, #{email})

test
@Test
public void test4() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

User user = new User(null, "admin", "123456", 16, "男", "12386@qq.com");

mapper.insertUser(user);

}

4.5 @Param 注解指定Map中key的名称
相对于4.2中,使用 param1 2 3 这种方式,@param可以直接在接口内把参数名称定义好。在map中额外增加一个以 param中 value值的key,届时可以通过key来取value。除此之外,arg 和 param的方式 仍然可用。
interface
User checkLoginByParam(@Param(“username”) String username, @Param(“password”) String password);
Mapper.xml

select * from table_users where username = #{username} and password = #{password}

test
@Test
public void test5() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

System.out.println(mapper.checkLoginByParam("root", "123"));

}

  1. Mybatis的各种查询功能
    在查询前,一定要清楚你自己查询出来的东西是什么,是一个实体对象,还是一个字面量,还是什么什么的。
    5.1 查询单个实体对象或者多个实体类对象
    若查询的结果为一条时,我们可以以实体类来作为返回结果,若查询的语句为多条时,我们不能以实体类来作为返回结果,需要一个集合容器,因为如果使用实体类作为返回结果,则底层调用的方法为 SqlSession.SelectOne。这时候去获取多条数据,则报错。而使用List集合作为返回对象时,则可获取一条,也可获取多条。
    其实该功能在上面第一次查询时已经使用过。不多讲。直接结合上面内容写代码。
    UserSelectMapper.interface
    package mybatis.mappers;

import mybatis.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserSelectMapper {

User selectUserById(@Param("id") Integer id);

List<User> selectAllUsers();

}
UserSelectMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 查询单个实体对象 根据id -->
<select id="selectUserById" resultType="User">
    select * from table_users where id = #{id}
</select>

<!-- 查询多个实体对象 -->
<select id="selectAllUsers" resultType="User">
    select * from table_users
</select>
Test @Test public void test1() {
SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
UserSelectMapper mapper = sqlSession.getMapper(UserSelectMapper.class);

System.out.println(mapper.selectUserById(2));
// User(id=2, username=root, password=123, age=15, gender=男, email=878035748@qq.com)

System.out.println(mapper.selectAllUsers());
/*
[User(id=2, username=root, password=123, age=15, gender=男, email=878035748@qq.com), 
User(id=4, username=jack, password=123513, age=15, gender=男, email=878035748@qq.com),
 User(id=5, username=admin, password=123456, age=16, gender=男, email=12386@qq.com)]
*/

}

5.2 查询单行单列数据信息
就是查询某列的平均值(avg),总条数啊(count)等等这些内容。在查询前,我们需要清楚的知道返回值类型应该包装成什么样子,例如。查询总条数,我返回的一定是一个整数类型,不可能返回小数类型。那我就可以使用Integer来表示,如果查询的是avg,则我可以用Double来表示。
在Mybatis中,官方已经为常用的一些包装对象。基本数据类型设置好了别名。具体如下。
下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。
别名映射的类型_bytebyte_longlong_shortshort_intint_integerint_doubledouble_floatfloat_booleanbooleanstringStringbyteBytelongLongshortShortintIntegerintegerIntegerdoubleDoublefloatFloatbooleanBooleandateDatedecimalBigDecimalbigdecimalBigDecimalobjectObjectmapMaphashmapHashMaplistListarraylistArrayListcollectionCollectioniteratorIterator

下面先写一个案例,展示查询数据库内总条数为多少。
UserSelectMapper.interface
public interface UserSelectMapper {
Integer selectCount();
}
UserServletMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!-- 查询数据库内总条数 -->
<select id="selectCount" resultType="integer">
    select count(*) from table_users
</select>
Test @Test public void test2() {
SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
UserSelectMapper mapper = sqlSession.getMapper(UserSelectMapper.class);

System.out.println(mapper.selectCount());

}
5.3 查出的结果以Map集合的形式返回封装
使用Map集合以应对于数据库查询出来的内容中,并没有与之对应的实体类对象。则可以使用map集合来返回。以后很常用。
5.3.1 以单个实体对象返回Map中
当以Map<> 对象的形式返回,底层仍然调用的是selectOne。
Mapper.interface
Map<String, Object> getOneUsersByMap(@Param(“id”) Integer id);
Mapper.xml

select * from table_users where id = #{id}

Test
@Test
public void test3() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
UserSelectMapper mapper = sqlSession.getMapper(UserSelectMapper.class);

Map<String, Object> oneUsersByMap = mapper.getOneUsersByMap(2);

System.out.println(oneUsersByMap);

}
5.3.2 以多个实体对象返回Map中
在获取多个实体对象到Map时,返回的是多个Map集合,自然,需要找一个可以存放Map容器的东西,也就是List<Map<>>。
Mapper.interface
List<Map<String , Object>> getAllUsersByMap();
Mapper.xml

select * from table_users

Test
@Test
public void test4() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
UserSelectMapper mapper = sqlSession.getMapper(UserSelectMapper.class);

List<Map<String, Object>> allUsersByMap = mapper.getAllUsersByMap();

allUsersByMap.forEach(System.out::println);

/*
{password=123, gender=男, id=2, age=15, email=878035748@qq.com, username=root}
{password=123513, gender=男, id=4, age=15, email=878035748@qq.com, username=jack}
{password=123456, gender=男, id=5, age=16, email=12386@qq.com, username=admin}
 */

}

5.3.3 @MapKey
若不想把Map位置于集合中,则可以使用@MapKey来解决,指定一个查询出来的数据的名称作为map返回数据的key。举例说明。
{password=123, gender=男, id=2, age=15, email=878035748@qq.com, username=root}
{password=123513, gender=男, id=4, age=15, email=878035748@qq.com, username=jack}
{password=123456, gender=男, id=5, age=16, email=12386@qq.com, username=admin}
查出来三条数据,接口为 Map<String, Object> getAllUsersByMap();
此时如果硬要查,则报错。无法把三条Map封装进一个Map中,因为他们没有key,则@MApKey则类似于Map中套Map,设置了一个key。于是大概就变成了。
Map<String, Map<String, Object>> 这种格式。则相当于指定了一个属性作为map的key
举例。
Interface
@MapKey(“id”)
Map<String, Object > getAllUsers();
Xml

select * from table_users

Test
@Test
public void test5() {

SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
UserSelectMapper mapper = sqlSession.getMapper(UserSelectMapper.class);

System.out.println(mapper.getAllUsers());

//{2={password=123, gender=男, id=2, age=15, email=878035748@qq.com, username=root},
// 4={password=123513, gender=男, id=4, age=15, email=878035748@qq.com, username=jack},
// 5={password=123456, gender=男, id=5, age=16, email=12386@qq.com, username=admin}}

}

  1. Mybatis处理模糊查询
    模糊查询不可以直接使用#{}来进行处理,因为 like %#{??}%’ 解析后会变为占位符, like ‘%?%’ 则,此时会直接的把他当作为字符串,而不是占位符,然mybatis找不到占位符,则会报错。
    有三种解决方式, 直接写xml内的sql,其他就忽略了
    6.1 采用字符串拼接方式
    select * from table_users where username like ‘%${value}%’
    6.2 采用sql内置函数拼接
    select * from table_users where username like concat(‘%’, #{value}, ‘%’})
    6.3 采用双引号拼接(最常用的方式)
    select * from table_users where username like “%”#{value}“%”
    6.4 三种示例
    interface
    package mybatis.mappers;

import mybatis.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface SpecialMapper {

List<User > getUserOne(@Param("value") String value);

List<User > getUserTwo(@Param("value") String value);

List<User > getUserThree(@Param("value") String value);

}
mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<select id="getUserOne" resultType="user">
    select * from table_users where email like '%${value}%'
</select>

<select id="getUserTwo" resultType="user">
    select * from table_users where email like concat('%', #{value}, '%')
</select>

<select id="getUserThree" resultType="user">
    select * from table_users where email like "%"#{value}"%"
</select>
Test import mybatis.mappers.SpecialMapper; import mybatis.pojo.User; import mybatis.utils.DataSourceUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test;

import java.util.List;

public class SpecialMapperTest {

@Test
public void test1() {

    SqlSession sqlSession = DataSourceUtils.getSqlSession();

    assert sqlSession != null;
    SpecialMapper mapper = sqlSession.getMapper(SpecialMapper.class);

    List<User> userOne = mapper.getUserOne("8");

    userOne.forEach(System.out::println);

}

@Test
public void test2() {

    SqlSession sqlSession = DataSourceUtils.getSqlSession();

    assert sqlSession != null;
    SpecialMapper mapper = sqlSession.getMapper(SpecialMapper.class);

    List<User> userTwo = mapper.getUserTwo("8");

    userTwo.forEach(System.out::println);

}

@Test
public void test3() {

    SqlSession sqlSession = DataSourceUtils.getSqlSession();

    assert sqlSession != null;
    SpecialMapper mapper = sqlSession.getMapper(SpecialMapper.class);

    List<User> userThree = mapper.getUserThree("8");

    userThree.forEach(System.out::println);

}

}

  1. 特殊的一些使用方法
    7.1 Mybatis批量删除简单使用
    批量删除在sql中一般有两种表达方式,一种是通过or,一种是通过in(),在还没有学习动态sql之前,是没办法做到or的。所以使用in函数来进行批量删除。
    在sql中,假设需要删除id为 1,2,3的三条sql,则需要
    delete from table_users where id in(1, 2, 3)
    也就是说,在括号内的,并不能是字符串,在mysql5版本,可以是字符串,但是他删除的则是开头的第一位数,无论你删除几遍,也是第一位数。所以我们并不能使用占位符的形式来进行拼接,也就是#{}的形式,我们需要使用拼接形式也就是${}
    Interface
    package mybatis.mappers;

import org.apache.ibatis.annotations.Param;

public interface BatchDeletionMapper {

void deleteBatch(@Param("sqlIn") String sqlIn);

}

Mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<delete id="deleteBatch">
    delete from table_users where id in(${sqlIn})
</delete>
Test import mybatis.mappers.BatchDeletionMapper; import mybatis.utils.DataSourceUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test;

public class BatchDeletionMapperTest {

@Test
public void test1() {

    SqlSession sqlSession = DataSourceUtils.getSqlSession();
    assert sqlSession != null;
    BatchDeletionMapper mapper = sqlSession.getMapper(BatchDeletionMapper.class);

    mapper.deleteBatch("8, 9");

}

}

7.2 Mybatis动态设置表名
在这里其实也就是一个#和$ 的区别,因为查询表的sql语句如下
select * from [table]
但是 table是不允许有字符串的,我们仍然需要 ${} 来进行字面量获取。
该功能用途大致为,有一个用户表,有一个vip表,字段一样,根据传回来的信息,来查询对应的表。
Interface
package mybatis.mappers;

import mybatis.pojo.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface GetTableNameMapper {

List<User > getTableName(@Param("tableName") String tableName);

}

Mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<delete id="deleteBatch">
    delete from table_users where id in(${sqlIn})
</delete>
Test import mybatis.mappers.GetTableNameMapper; import mybatis.pojo.User; import mybatis.utils.DataSourceUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test;

import java.util.List;

public class GetTableNameTest {

@Test
public void test1() {

    SqlSession sqlSession = DataSourceUtils.getSqlSession();

    assert sqlSession != null;
    GetTableNameMapper mapper = sqlSession.getMapper(GetTableNameMapper.class);

    List<User> table_users = mapper.getTableName("table_users");

    table_users.forEach(System.out::println);

}

}

7.3 添加功能获取自增的主键
因为添加方式的返回值,都是固定的,包括删除喝修改,都是受影响的条数,那么就会把返回自增的主键值,放在实体对象内。比如id。需要在xml中开启两个属性,一个是

useGeneratedKeys=“true”

keyProperty=“id”
Interface
package mybatis.mappers;

import mybatis.pojo.User;

public interface GetAutoKeyMapper {

void insertUser(User user);

}
Mapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    insert into table_users values(NULL, #{username}, #{password}, #{age}, #{gender}, #{email})
</insert>
Test 1

7.4 使用全局配置处理字段名和属性名不一致的情况
大致意思是,Java的命名规则为驼峰法, 在mysql中字段命名规则为xxx_xxx,导致Java成员变量和mysql字段名称不一致,无法查询出内容,有两种解决方式。
第一种,使用mysql,在查询的时候起别名。

select emp_id empId, emp_name empName, age, gender from table_emp where emp_id = #{id}

第二种方式,直接在全局配置内配置setting。开启自动驼峰映射

<setting name="mapUnderscoreToCamelCase" value="true"/>
需要注意的是,要满足一定规则,也就是 emp_id --> empId, emp_name --> empName

7.5 使用ResultMap处理7.4的情况

这种属于自定义来自己指定内容,直接上代码就能看明白
Interface
Emp selectEmpByIdButIsResultMap(@Param(“id”) Integer id);
Mapper.xml





select * from table_emp where emp_id = #{id} 在Select标签中,也不再是resultType,返回值类型了,变成了 resultMap。resultMap的属性值为新标签的id。 在resultMap标签中,id是标识,type要处理哪个类的映射。内部目前用到的,id标签,表示主键。剩下的result表示普通字段的对应。 column属性,是在数据库内的字段名称 property属性,是对应的实体类属性
  1. 多表(连表)查询
    8.1 使用联级处理多对一的映射关系
    Interfac
    Emp selectEmpAndDept(@Param(“id”) Integer id);
    Mapper.xml







select * from table_emp left join table_dept on table_emp.dept_id = table_dept.dept_id where table_emp.emp_id = #{id} Test @Test public void test3() {
SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

System.out.println(mapper.selectEmpAndDept(1));

}

8.2 使用association处理多对一的映射关系
association是专门用来处理多对一的映射关系。主要用来处理,实体类类型的属性。
其实说白了就是套娃。把属性当成一个对象,然后对象内在设置属性。

property表示对应的属性名称叫什么,JavaType表示你要对什么类型进行处理。









select * from table_emp left join table_dept on table_emp.dept_id = table_dept.dept_id where table_emp.emp_id = #{id} 其余的和8.1一样。Test @Test public void test3() {
SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

System.out.println(mapper.selectEmpAndDept(1));

}

8.3 使用分步查询处理多对一的映射关系

第一步,首先先查出来整个emp表内的数据,得到dept_id
Emp stepByStepSelectByEmp(@Param(“id”) Integer id);
xml







select * from table_emp where emp_id = #{id} 此时,对于 association标签内的属性,下面会详细解释。 然后进行第二步,查询出来所有的部门表内的数据,也就是部门id和部门name。 Dept stepByStepSelectByDept(@Param("id") Integer deptId); xml select * from table_dept where dept_id = #{id} 此时,就可以对应起来了,在上面association标签内,property依然是属性。select为查询方法需要查出来的内容,也就是现在这个查询的唯一标识。column是查出来需要下次查询的字段。 测试方法 @Test public void test4() {
SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

System.out.println(mapper.stepByStepSelectByEmp(1));

}

8.3.1 分布查询的优点-延迟加载

lazyLoadingEnabled延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。true | falsefalseaggressiveLazyLoading开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载(参考lazyLoadTriggerMethods)。true | falsefalse (在 3.4.1 及之前的版本中默认为 true)
延迟加载就是按需加载,举上述例子来说,假设你只需要一个员工Name,则只会执行一条Sql,也就是
select * from table_emp where id = ?
然后返回给你对应的员工名称。与之关联的dept的sql则不会执行,因为没有用到。
开启该功能的前提是,在全局配置文件mybatis-config.xml中的setting标签内设置 lazyLoadingEnabled 为 true。
aggressiveLazyLoading则和该属性相反,他一旦设置为true,则会默认全部加载,哪怕lazyLoadingEnabled也为true。他俩一般一起出现。若全局配置懒加载,但是有部分的sql想要完全加载,也是有办法的。如下







select * from table_emp where emp_id = #{id}

在相对应关联的 association中设置 fetchType为eager,则为开启全部加载,与之对应还有一个lazy,则为懒加载。

8.4 通过collection来处理一对多的映射关系
首先在实体类内肯定有改变,因为是一对多,所以肯定在实体类中有对多的集合。
package mybatis.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Dept {

private Integer deptId;

private String deptName;

private List<Emp > empList;

}

其实一对多就是把东西塞到了集合里,上代码然后解释。
Interface
Dept getDeptAndEmpByDeptId(@Param(“id”) Integer deptId);
Mapper.xml









select * from table_dept left join table_emp on table_dept.dept_id = table_emp.dept_id where table_dept.dept_id = #{id}; Test @Test public void test5() {
SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);

System.out.println(mapper.getDeptAndEmpByDeptId(1));

}
结果
Dept(deptId=1, deptName=A, empList=[Emp(empId=1, empName=张三, age=19, gender=男, dept=null), Emp(empId=6, empName=郭八, age=15, gender=男, dept=null), Emp(empId=7, empName=安九, age=18, gender=男, dept=null)])
其实和多对一一样,但是从association换成了collection,然后以前是javaType,但是collection中是ofTpye,也就是集合内是什么类型的对象。写为emp即可。

8.5 使用分布查询来查询一对多的关系
和多对一是一样的,还是一套模板,只需要搞清楚他们之间的关系即可
DeptMapper.interface
Dept getDeptAndEmpByStepOne(@Param(“deptId”) Integer deptId);
DeptMapper.xml









select * from table_dept where dept_id = #{deptId} EmpMapper.interface List getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId); EmpMapper.xml select * from table_emp where dept_id = #{deptId} Test @Test public void test6() {
SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);

System.out.println(mapper.getDeptAndEmpByStepOne(1));

}
结果
Dept(deptId=1, deptName=A, empList=[Emp(empId=1, empName=张三, age=19, gender=男, dept=null), Emp(empId=6, empName=郭八, age=15, gender=男, dept=null), Emp(empId=7, empName=安九, age=18, gender=男, dept=null)])

  1. 动态SQL
    9.1 搭建环境
    在原有的基础配置上,不变,清空所有的内容,留下util,创建pojo。且只有一个Emp

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Emp {

private Integer empId;

private String empName;

private Integer age;

private String gender;

}

然后创建Mapper和对应的Xml 分别为
DynamicMapper.interface
DynamicMapper.xml
里面仅有最基础的内容。

9.2 if标签
根据对象条件查询出所对应的内容、
Mapper.interface
// 根据条件查询,不确定有几个对象。所以用List集合来装载,多条件肯定是根据Emp字段来查询所以传入对象
List getEmpByCondition(Emp emp);
Mapper.xml

select * from table_emp where

emp_name = #{empName}


if是根据test属性内条件。来决定是否拼接if标签内的内容。 因为我们上面传入的是一个Emp对象。则test内可以直接使用emp对象内的属性来进行判断。第一个,判断是否为空。第二个,判断是否为空字符。如果都不是,则可以拼接内容,拼接为以下
select * from table_emp where emp_name = ?;

9.3 where 标签
9.3.1 (1=1)
在if语句中,有一种情况,就是多个if的情况下。会出现这个情况
select * from table_emp where

emp_name = #{empName}


and age = #{age}

假设,第一个if不成立,那么第二个if成立,就会直接拼接在where后面
select * from table_emp where and age = ?;
则是sql语句直接报错。如果想要解决这种情况,有两种办法,在前面接上一个永远成立的条件。并且把if标签内全部加上and
select * from table_emp where 1 = 1

and emp_name = #{empName}


and age = #{age}

这种情况,可以解决这种问题,但是在mybatis中,提供了一个where标签

9.3.2 where
select * from table_emp where

emp_name = #{empName}


and age = #{age}

还是这个sql语句,如果需要她不报错,则可以在所有if的最外层,套上一个where。并且在sql中去掉where关键字
select * from table_emp


emp_name = #{empName}


and age = #{age}


如果,第一个if成立,则会自动在后面加上where关键字,然后拼接第一个if内的内容。
如果还是上述情况,则会自动去除age前面的 and关键字。变为。
select * from table_emp where age = ?;
当两个条件都不满足的时候,则不会生成任何内容。

9.4 trim标签
暂时感觉where好用。以后在说
prefix,suffix在标签中内容前面或者后面添加指定内容。
prefixOverrides, suffixOverrides在标签前面或者后面去除指定内容。

9.5 choose,when,otherwise
就是if elseif,else,只不过结构是这样的,在choose内没有属性。从when开始。







9.6 forEach标签
使用批量操作的时候,都会使用forEach来实现。如果是一个LIst集合的参数的话,要想在xml中访问,并且没有设置@param的情况下,需要使用 list来访问。
9.6.1 批量添加
首先,添加的返回值类型要么是添加了几条数据,要么是void。我们就使用void即可,然后内容因为是批量添加,一条也好,多条也好,使用List集合来作为属性。
List 使用@Param 来指明属性的名称
Interface
void insertMoreEmp(@Param(“empList”) List empList);
xml

insert into table_emp(emp_id, emp_name, age, gender) values

(null, #{emp.empName}, #{emp.age}, #{emp.gender})


foreach,collection表示从那个集合属性里面遍历,也就是我们的 empList,然后item是单个遍历出来的对象,separator是分隔符,每一次循环和每一次循环之间用 , 分割。
9.6.2 批量删除
其实和批量增加是一样的,会了就会。
Interface
void deleteMoreEmp(@Param(“empArray”) Integer[] empId);
xml

delete from table_emp where emp_id in (

#{empId}

)

Test
@Test
public void test3() {

Integer[] integers = new Integer[15];

for (int i = 8; i <= 22; i++) {
    integers[i-8] = i;
}

SqlSession sqlSession = DataSourceUtils.getSqlSession();

assert sqlSession != null;
DynamicMapper mapper = sqlSession.getMapper(DynamicMapper.class);

mapper.deleteMoreEmp(integers);

}

9.7 sql, include标签
可以用来记录一段sql, 在使用的地方使用 include标签来引入

  1. Mybatis的缓存
    和浏览器中的缓存相同,把一些没有变动过的东西缓存到本地,在下次查询的时候,如果没有增删改操作,则直接从缓存内取出数据,不会在去重新查询数据库。
    10.1 Mybatis的一级缓存
    Mybatis的一级缓存是默认开启的,就算仅仅搭建了一个mybatis框架。什么都没有做,那他也是默认开启的。可以直接使用的。一级缓存是Session级别的,在同一个Session中,查询的数据会被缓存,下一次查询,不会在去访问数据库,从缓存中取出。

使一级缓存失效的四种情况:
不同的SqlSession对应不同的一级缓存
同一个SqlSession但是查询条件不同
同一个SqlSession查询期间执行了任意一个增删改操作
同一个SqlSession两次查询期间执行了手动清除缓存操作

10.2 Mybatis的二级缓存
二级缓存是SqlSessionFactory级别的,一级缓存是SqlSession级别的。同一个SqlSessionFactory创建出来的SqlSession查询结果会被缓存,若在此后再次执行相同的查询操作,结果就会从缓存中取出

二级缓存开启的条件
在核心配置文件中,设置全局配置属性cacheEnabled=“true”。默认为true。不需要设置。
在映射文件,也就是Mapper.xml中,设置标签 也就是如下:

<?xml version="1.0" encoding="UTF-8" ?>
<cache />
二级缓存必须在SqlSession关闭或提交后才有效 查询的数据所转换的实体类型必须实现序列化的接口

使二级缓存失效的情况
两次查询之间执行了任意的增删改,都会使一级缓存和二级缓存一起失效。

  1. Mybatis逆向工程
    pom.xml
<?xml version="1.0" encoding="UTF-8"?>


4.0.0

<groupId>org.example</groupId>
<artifactId>mybatis_mbg</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

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

<dependencies>

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.11</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.29</version>
    </dependency>
</dependencies>

<!-- 控制maven在构建过程的相关配置 -->
<build>
    <!-- 构建过程用到的插件-->
    <plugins>
        <!-- 具体地插件,逆向工程是以插件的形式存在-->
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.0</version>

            <!-- 插件的依赖 -->
            <dependencies>
                <dependency>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-core</artifactId>
                    <version>1.3.2</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
  1. Mybatis分页插件
    limit index, pageSize

pageSize: 每页显示的条数
pageNum: 当前页的码页
index: 当前页起始索引,公式为: (pageNum-1)*pageSize
count: 总记录数
totalPage: 总页数, totalPage = count / pageSize
if (count % pageSize != 0) {
totalPage += 1;
}

12.1 使用步骤
添加Pom依赖

com.github.pagehelper
pagehelper
5.1.2

配置插件
在mybatis-config.xml中有一个plugins,在内配置




然后就可以直接使用了,新建Test类,需要借助PageHelper.startPage来完成。
@Test
public void test1() throws IOException {

EmpMapper mapper = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")).
        openSession().getMapper(EmpMapper.class);

// 在查询之前开启分页功能
PageHelper.startPage(1, 4);

List<Emp> list = mapper.selectByExample(null);

list.forEach(System.out::println);

}

12.2 通过分页插件获取相关数据
PageHelper.startPage(1, 4); 可以获取一个Page对象
Page objects = PageHelper.startPage(1, 4);
输出这个Page对象就会发现里面包含了需要使用到的信息。
Page{count=true, pageNum=1, pageSize=4, startRow=0, endRow=4, total=7, pages=2, reasonable=false, pageSizeZero=false}
但是有时候这些信息并不够使用,所以可以使用PageInfo对象,list是查询出来的结果。要对list进行分页
PageInfo pageInfo = new PageInfo<>(list);

System.out.println(pageInfo);
得到如下结果。
PageInfo{pageNum=1, pageSize=4, size=4, startRow=1, endRow=4, total=7,
pages=2, list=Page{count=true, pageNum=1, pageSize=4, startRow=0,
endRow=4, total=7, pages=2, reasonable=false, pageSizeZero=false},
prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false,
hasNextPage=true, navigatePages=8, navigateFirstPage=1, navigateLastPage=2, navigatepageNums=[1, 2]}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mybatis3快速上手(详细) 的相关文章

随机推荐

  • Linux命令自动补齐oh-my-zsh插件及美化主题超详细

    安装zsh 1 查看系统当前使用的shell echo SHELL 2 查看系统是否安装了zsh cat etc shells 3 用yum安装zsh yum y install zsh 4 查看shell列表 cat etc shells
  • [附源码]计算机毕业设计Python游戏交易平台(程序+源码+LW文档)

    该项目含有源码 文档 程序 数据库 配套开发软件 软件安装教程 项目运行 环境配置 Pychram社区版 python3 7 7 Mysql5 7 HBuilderX list pip Navicat11 Django nodejs 项目技
  • C#中Socket的Accept()和BeginAccept()的区别

    C 中Socket的Accept 和BeginAccept 的区别 区别在于 Accept 是同步的 BeginAccept 是异步的 调用accept 或者BeginAccept 函数来接受客户端的连接 这就可以和客户端通信了 Begin
  • 五分钟学会一门编程语言?

    大家好 我是可乐 看到标题 不出意外的话 你肯定开始骂我了 标题党 什么编程语言五分钟就能学会 其实我本来也是不相信的 但是学过了才知道这是真的 1 Brainfuck 看到这个小标题 不要误会 我没有骂人 这就是今天文章的主人公 也就是让
  • 如何理解BIO、NIO、AIO的区别

    一 同步阻塞I O BIO 同步阻塞I O 服务器实现模式为一个连接一个线程 即客户端有连接请求时服务器就需要启动一个线程进行处理 如果这个连接不做任何事情会造成不必要的线程开销 可以通过线程池机制来改善 BIO方式适用于连接数目比较小且固
  • Leetcode 124. 二叉树中的最大路径和

    题目内容 给定一个非空二叉树 返回其最大路径和 本题中 路径被定义为一条从树中任意节点出发 沿父节点 子节点连接 达到任意节点的序列 该路径至少包含一个节点 且不一定经过根节点 示例 1 输入 1 2 3 1 2 3 输出 6 示例 2 输
  • 使用 js 实现 贷款计算器功能

    table tr th Enter Loan Data th td td th Loan Balance Interest Payments th tr tr td Amount of Loan td tr table
  • Java NIO介绍(二)————无堵塞io和Selector简单介绍

    无堵塞IO介绍 既然NIO相比于原来的IO在读取速度上其实并没有太大区别 因为NIO出来后 IO的低层已经以NIO为基础重新实现了 那么NIO的优点是什么呢 NIO是一种同步非阻塞的I O模型 也是I O多路复用的基础 而且已经被越来越多地
  • 【我的Java笔记】List集合中set()方法的使用

    方法 E set int index E element 首先看一下API里对List集合中的set 方法的描述 例 使用List集合中的set 方法进行冒泡排序 import java util ArrayList public clas
  • WebDriverException unexpectedly exited. Status code was: 2

    raise WebDriverException selenium common exceptions WebDriverException Message Service D Projects test geckodriver exe u
  • 计数器实现七分频

    七分频 即将输入信号的频率变为原来的七分之一 本文用计数器实现输入信号的七分频 一 画出七分频的时序逻辑 实现原理 图中用到了两个计数器 一个上升沿触发一个下降沿触发 且每当计数器从0计数到6时 复位 中间信号sig1 sig2分别在cnt
  • xhtml2pdf如何支持中文

    这段时间在做一个图片PDF的项目 需要把网页转换成PDF 找到了python的xhtml2pdf这个库 个方面都满意 只是对中文的支持不好 html上的中文转换成PDF后都成了乱码 貌似中文网站都没有找到合适的解决办法 只能求助于万能的go
  • 传统语音增强——基本的维纳滤波语音降噪算法

    一 维纳滤波的基本原理 基本维纳滤波就是用来解决从噪声中提取信号问题的一种过滤 或滤波 方法 它基于平稳随机过程模型 且假设退化模型为线性空间不变系统的 实际上这种线性滤波问题 可以看成是一种估计问题或一种线性估计问题 基本的维纳滤波是根据
  • error LNK2001: 无法解析的外部符号 “void __cdecl cv::cvtColor

    c 调用opencv时报错了 error LNK2001 无法解析的外部符号 void cdecl cv cvtColor 现在发现有两个可能的原因 原因1 没有添加lib库 需要添加lib库 VC 目录 包含目录 VC 目录 库目录 链接
  • 网络安全入门学习练手——CS伪装钓鱼网站

    文章目录 一 实验环境 二 使用工具和目标 三 开始复现 1 启动Cobalt Strike服务器端 打开Cobalt Strike客户端 2 设置监听器 3 网站克隆 4 在受害者端输入克隆网站对应的ip 5 测试 四 拓展 让钓鱼网址挂
  • 记录一次mac电脑安装git并在idea中使用的问题

    一 安装Git 下载地址 https sourceforge net projects git osx installer 点击下载最新版就可以了 下载速度很快的 下载完直接打开 默认安装即可 安装完成直接在命令行用root用户执行 git
  • L1-020 帅到没朋友(java)

    1 题目详情 当芸芸众生忙着在朋友圈中发照片的时候 总有一些人因为太帅而没有朋友 本题就要求你找出那些帅到没有朋友的人 输入格式 输入第一行给出一个正整数N 100 是已知朋友圈的个数 随后N行 每行首先给出一个正整数K 1000 为朋友圈
  • gcc make makefile 的基本介绍

    一 gcc 1 在window操作系统下 编译工具用集成开发环境 在Linux操作系统下没有很好的集成环境 用的编译器是gcc 2 程序的编译分为四个阶段 由 c到可执行程序 1 预编译 2 编译 3 汇编 4 链接 3 编译程序 1 一步
  • PTAMM阅读笔记之SLAM概述(五)

    1 同时定位与地图创建允许机器人在未知环境中 依靠自身所带的传感器递增式地创建环境地图 并同时给出机器人所在位置 2 移动机器人的定位有两种类型 全局定位 绝对定位 Global Absolute Localization 和位置跟踪 Po
  • Mybatis3快速上手(详细)

    因为编辑器不互通 所以可以直接打开有道云看 有道云链接 Mybatis的初入 创建Maven项目工程 因为Mybatis属于数据访问层的操作 我们需要引入相关依赖 mysql mysql connector java 8 0 29 org