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

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: [Java]Mybatis学习笔记(动力节点老杜)(五)

MyBatis 小技巧

#{} 与 ${}

接口方法

/**
 * 根据汽车类型获取汽车信息
 * 
 * @param carType 汽车类型
 * @return 汽车信息组成的列表
 */
List<Car> selectByCarType(String carType);

SQL

<select id="selectByCarType" resultType="cw.mybatis.pojo.Car">
  select id,
         car_num      as carNum,
         brand,
         guide_price  as guidePrice,
         produce_time as produceTime,
         car_type     as carType
  from t_car
  where car_type = #{carType}
</select>
<select id="selectByCarType" resultType="cw.mybatis.pojo.Car">
  select id,
         car_num      as carNum,
         brand,
         guide_price  as guidePrice,
         produce_time as produceTime,
         car_type     as carType
  from t_car
  where car_type = ${carType}
</select>

测试

@Test
public void test01() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    // 获取CarMapper接口的代理类对象
    // 底层为CarMapper接口生成了字节码,同时创建了实现类的对象
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    List<Car> cars = mapper.selectByCarType("新能源");
    cars.forEach(System.out::println);
    SqlSessionUtil.close();
}

#{} 结果

  • 先对SQL语句进行编译,采用 ?作为占位符,然后使用查询参数填充占位符
[main] DEBUG cw.mybatis.mapper.CarMapper.selectByCarType - ==>  
Preparing: 
select 
  id, 
  car_num as carNum, 
  brand, guide_price as guidePrice, 
  produce_time as produceTime, 
  car_type as carType 
from t_car 
where car_type = ?
[main] DEBUG cw.mybatis.mapper.CarMapper.selectByCarType - ==> 
Parameters: 新能源(String)
[main] DEBUG cw.mybatis.mapper.CarMapper.selectByCarType - <==      
Total: 2
查询出来的数据:
Car{id=2, carNum='1002', brand='奔驰E300L', guidePrice=55.0, produceTime='2022-11-11', carType='新能源'}
Car{id=20, carNum='4444', brand='奔驰C200&&&', guidePrice=32.0, produceTime='2000-10-10', carType='新能源'}

${} 结果

  • 直接将查询参数的数值直接采用字符串拼接的方式,拼接到SQL语句中,然后再进行SQL语句的编译
[main] DEBUG cw.mybatis.mapper.CarMapper.selectByCarType - ==>  
Preparing: 
select 
  id, 
  car_num as carNum, 
  brand, 
  guide_price as guidePrice, 
  produce_time as produceTime, 
  car_type as carType 
from t_car 
where car_type = 新能源
[main] DEBUG cw.mybatis.mapper.CarMapper.selectByCarType - ==> 
Parameters: 
org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.sql.SQLSyntaxErrorException: 
  Unknown column '新能源' in 'where clause'
### The error may exist in CarMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: 
select  id,          
        car_num      as carNum,          
        brand,
        guide_price  as guidePrice,
        produce_time as produceTime,
        car_type     as carType   
from t_car   
where car_type = 新能源
### Cause: java.sql.SQLSyntaxErrorException: 
Unknown column '新能源' in 'where clause'

#{} 与 ${} 的区别

  • #{}: 底层使用PreparedStatement。
  • 特点:先进行SQL语句的编译,然后给SQL语句的占位符问号?传值。
  • 给 ? 传值时是否添加 ‘’ 根据传递的数据类型
  • 可以避免SQL注入的风险。
  • ${}:底层使用Statement。
  • 特点:先进行SQL语句的拼接,然后再对SQL语句进行编译。
  • 存在SQL注入的风险。
  • 优先使用#{},这是原则。避免SQL注入的风险。#{}不能实现在考虑${}

${} 的使用场景 - 升序或降序排序

  • 从数据库查询数据时,进行排序

接口方法

/**
 * 查询所有的汽车信息,并进行升序或降序排序
 * 
 * @param ascOrDesc 升序或降序排序
 * @return 排序后的汽车信息组成的集合
 */
List<Car> selectAllAscOrDesc(String ascOrDesc);

SQL

<select id="selectAllAscOrDesc" resultType="cw.mybatis.pojo.Car">
  select id,
         car_num      as carNum,
         brand,
         guide_price  as guidePrice,
         produce_time as produceTime,
         car_type     as carType
  from t_car
  order by produce_time #{ascOrDesc};
</select>
<select id="selectAllAscOrDesc" resultType="cw.mybatis.pojo.Car">
  select id,
         car_num      as carNum,
         brand,
         guide_price  as guidePrice,
         produce_time as produceTime,
         car_type     as carType
  from t_car
  order by produce_time ${ascOrDesc};
</select>

测试

@Test
public void test02() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    // 查询所有的汽车信息,并降序排序
    List<Car> cars = mapper.selectAllAscOrDesc("desc");
    cars.forEach(System.out::println);
    SqlSessionUtil.close();
}

#{} 结果

  • 会先进行SQL语句的编译,将#{}的位置使用占位符?替换,然后再使用查询参数进行填充
[main] DEBUG cw.mybatis.mapper.CarMapper.selectAllAscOrDesc - ==>  
Preparing: 
select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType 
from t_car 
order by produce_time ?;
[main] DEBUG cw.mybatis.mapper.CarMapper.selectAllAscOrDesc - ==> 
Parameters: desc(String)
填充后的SQL为
select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType 
from t_car 
order by produce_time 'desc'; 
存在语法错误
org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: 
  java.sql.SQLSyntaxErrorException: 
  You have an error in your SQL syntax; 
  check the manual that corresponds to your MySQL server version for the right syntax to use near ''desc'' at line 8
### The error may exist in CarMapper.xml
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: select id,          car_num      as carNum,          brand,          guide_price  as guidePrice,          produce_time as produceTime,          car_type     as carType   from t_car   order by produce_time ?;
### Cause: java.sql.SQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''desc'' at line 8

${} 结果

  • 先将查询参数与SQL语句进行字符串拼接,然后再进行SQL语句的编译
[main] DEBUG cw.mybatis.mapper.CarMapper.selectAllAscOrDesc - ==>  
Preparing: 
select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType 
from t_car 
order by produce_time desc;
符合预期,可以进行数据的查询并进行排序
[main] DEBUG cw.mybatis.mapper.CarMapper.selectAllAscOrDesc - ==> Parameters: 
[main] DEBUG cw.mybatis.mapper.CarMapper.selectAllAscOrDesc - <==      Total: 17

${} 小结

  • 如果需要SQL语句的关键字放到SQL语句中,只能使用${},因为#{}是以值的形式放到SQL语句当中的。

${} 的使用场景 - 拼接表名

  • 向SQL语句当中拼接表名,就需要使用${}
  • 现实业务当中,可能会存在分表存储数据的情况。因为一张表存的话,数据量太大。查询效率比较低。可以将这些数据有规律的分表存储,这样在查询的时候效率就比较高。因为扫描的数据量变少了。
  • 如,日志表:专门存储日志信息的。如果t_log只有一张表,这张表中每一天都会产生很多log,慢慢的,这个表中数据会很多。我们可以每天生成一个新表。每张表以当天日期作为名称,例如:t_log_20220901、t_log_20220902…当我们需要知道某一天的日志信息,假设今天是20220901,那么我们可以直接查:t_log_20220901的表即可。

数据库表准备

use dbtest;
create table t_log_20220901
(
    id   int primary key auto_increment,
    log  varchar(255),
    time datetime
);
INSERT INTO `t_log_20220901` (`id`, `log`, `time`)
VALUES (1, '日志信息日志信息日志信息', '2022-09-01 11:06:31');
INSERT INTO `t_log_20220901` (`id`, `log`, `time`)
VALUES (2, '安全警告安全警告安全警告', '2022-09-01 11:07:20');
create table `t_log_20220902`
(
    id   int primary key auto_increment,
    log  varchar(255),
    time datetime
);
INSERT INTO `t_log_20220902` (`id`, `log`, `time`) 
VALUES (1, '插入数据', '2022-09-02 11:08:31');
INSERT INTO `t_log_20220902` (`id`, `log`, `time`) 
VALUES (2, '删除数据', '2022-09-02 11:08:45');

数据库表对应的Java类

package cw.mybatis.pojo;
/**
 * ClassName: Log
 * Package: cw.mybatis.pojo
 * Description:
 *
 * @Author tcw
 * @Create 2023-05-25 11:24
 * @Version 1.0
 */
public class Log {
    private Integer id;
    private String log;
    private String time;
    public Log() {
    }
    public Log(Integer id, String log, String time) {
        this.id = id;
        this.log = log;
        this.time = time;
    }
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getLog() {
        return log;
    }
    public void setLog(String log) {
        this.log = log;
    }
    public String getTime() {
        return time;
    }
    public void setTime(String time) {
        this.time = time;
    }
    @Override
    public String toString() {
        return "Log{" + "id=" + id + ", log='" + log + '\'' + ", time='" + time + '\'' + '}';
    }
}

接口声明

public interface LogMapper {
    /**
     * 根据日期查询不同的数据库表中的全部信息
     * 
     * @param date 日期字符串
     * @return 与日期对应的数据表中全部信息组成的集合
     */
    List<Log> selectAllByTable(String date);
}

SQL映射文件

<mapper namespace="cw.mybatis.mapper.LogMapper">
  <select id="selectAllByTable" resultType="cw.mybatis.pojo.Log">
    select id, log, `time`
    from t_log_${date}
  </select>
</mapper>

修改 MyBatis 核心配置文件

<mappers>
  <mapper resource="CarMapper.xml"/>
  <mapper resource="LogMapper.xml"/>
</mappers>

测试

@Test
public void selectAllByTable() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    // 获取代理对象
    LogMapper mapper = sqlSession.getMapper(LogMapper.class);
    // 查询数据
    List<Log> logs20220901 = mapper.selectAllByTable("20220901");
    logs20220901.forEach(System.out::println); // 打印信息
    List<Log> logs20220902 = mapper.selectAllByTable("20220902");
    logs20220902.forEach(System.out::println); // 打印信息
    // 关闭资源
    SqlSessionUtil.close();
}
直接将日期字符串以字符串拼接的方式与SQL语句进行拼接,然后再进行SQL语句的编译
[main] DEBUG cw.mybatis.mapper.LogMapper.selectAllByTable - ==>  
Preparing: select id, log, `time` from t_log_20220901
[main] DEBUG cw.mybatis.mapper.LogMapper.selectAllByTable - ==> Parameters: 
[main] DEBUG cw.mybatis.mapper.LogMapper.selectAllByTable - <==      Total: 2
Log{id=1, log='日志信息日志信息日志信息', time='2022-09-01 11:06:31'}
Log{id=2, log='安全警告安全警告安全警告', time='2022-09-01 11:07:20'}
[main] DEBUG cw.mybatis.mapper.LogMapper.selectAllByTable - ==>  
Preparing: select id, log, `time` from t_log_20220902
[main] DEBUG cw.mybatis.mapper.LogMapper.selectAllByTable - ==> Parameters: 
[main] DEBUG cw.mybatis.mapper.LogMapper.selectAllByTable - <==      Total: 2
Log{id=1, log='插入数据', time='2022-09-02 11:08:31'}
Log{id=2, log='删除数据', time='2022-09-02 11:08:45'}
如果是 #{} 会先进行SQL语句的编译,
编译后的SQL语句为:Preparing: select id, log, `time` from t_log_?
使用日期字符串填充后,SQL语句变为:Preparing: select id, log, `time` from t_log_'20220902'

${} 的使用场景 - 批量删除(一次删除多条记录)

  • 批量删除的SQL语句有两种写法:
-- 第一种 or :
delete from t_car where id=1 or id=2 or id=3;
-- 第二种 in :
delete from t_car where id in(1,2,3);

接口声明

/**
 * 根据id批量删除数据库表中的信息
 * 
 * @param ids 需要进行删除操作的信息的id组成的字符串
 * @return 删除记录的条数
 */
int deleteBatch(String ids);

SQL

<delete id="deleteBatch">
  delete from t_car
  where id in (${ids});
</delete>
<!-- 
如果要采用 delete from t_car where id=1 or id=2 or id=3;
这种形式则需要使用动态SQL
-->

测试

@Test
public void test03() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    int deleteCount = mapper.deleteBatch("2, 3, 4");
    System.out.println(deleteCount);
    sqlSession.commit()
    SqlSessionUtil.close();
}
先进行字符串拼接,然后再进行SQL语句的编译
[main] DEBUG cw.mybatis.mapper.CarMapper.deleteBatch - ==>  
Preparing: delete from t_car where id in (2, 3, 4);
[main] DEBUG cw.mybatis.mapper.CarMapper.deleteBatch - ==> Parameters: 
[main] DEBUG cw.mybatis.mapper.CarMapper.deleteBatch - <==    Updates: 3
如果使用 #{} 先进行SQL语句的编译
编译后的SQL为 delete from t_car where id in (?);
使用查询参数填充占位符后SQL为 delete from t_car where id in ('2, 3, 4');
会报语法错误

模糊查询(like)

  • 需求:根据汽车品牌进行模糊查询
  • SQL如下:
select * from t_car where brand like '%奔驰%';
select * from t_car where brand like '%比亚迪%';

可以采取的方式分析

  • 由于#{}是先对SQL语句进行编译,将#{}的位置使用JDBC中的占位符?进行替换,然后再使用参数来填充占位符,如果用于填充占位符的参数为字符串类型,则填充后会携带有引号;${}是先采用字符串拼接的方式,将参数和SQL语句字符串进行拼接,然后再对SQL语句进行编译,所以用于填充占位符的参数为字符串类型,与SQL语句拼接后不会有引号
  • 注意:SQL语句中,引号内的 ? ,如 '%?%'不会被认为是JDBC的占位符,而会被认为是字符串的一部分
  • 因此可以有如下四种方案:
  • 第一种方案:'%${brand}%',字符串拼接后为 '%brand%'
  • 第二种方案:concat函数,这个是mysql数据库当中的一个函数,专门进行字符串拼接concat('%',#{brand},'%'),SQL编译后为 concat('%', ?,'%')
  • 第三种方案:concat('%','${brand}','%'),字符串拼接后为 concat('%','brand','%')
  • 第四种方案:"%"#{brand}"%",SQL编译后为"%"?"%"
  • 让JDBC可以识别出充当占位符的 ?
  • MySQL会自动进行字符串的拼接
  • 也可以在传入的字符串中将模糊匹配写好,如'%宝马%',将这一整个字符串传递

接口声明

/**
 * 根据汽车的品牌进行模糊查询
 * 
 * @param brand 汽车品牌字符串
 * @return 查询出来的汽车信息
 */
List<Car> selectByBrandLike(String brand);

SQL

<select id="selectByBrandLike" resultType="cw.mybatis.pojo.Car">
  select id,
         car_num      as carNum,
         brand,
         guide_price  as guidePrice,
         produce_time as produceTime,
         car_type     as carType
  from t_car
  where brand like concat('%', #{brand}, '%');
</select>

测试

@Test
public void test04() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    List<Car> cars = mapper.selectByBrandLike("比亚迪");
    cars.forEach(System.out::println);
    SqlSessionUtil.close();
}
先进行SQL语句的编译
select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car 
where brand like concat('%', ?, '%');
使用数据填充占位符(采用 #{} )
select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car 
where brand like concat('%', '比亚迪', '%');
[main] DEBUG cw.mybatis.mapper.CarMapper.selectByBrandLike - ==>  
Preparing: 
  select id, car_num as carNum, brand, guide_price as guidePrice, produce_time as produceTime, car_type as carType from t_car where brand like concat('%', ?, '%');
[main] DEBUG cw.mybatis.mapper.CarMapper.selectByBrandLike - ==> 
Parameters: 比亚迪(String)
[main] DEBUG cw.mybatis.mapper.CarMapper.selectByBrandLike - <==      Total: 5
Car{id=9, carNum='1111', brand='比亚迪汉', guidePrice=10.0, produceTime='2020-11-11', carType='电车'}
Car{id=15, carNum='1333', brand='比亚迪汉', guidePrice=10.0, produceTime='2020-11-11', carType='电车'}
Car{id=16, carNum='1333', brand='比亚迪汉', guidePrice=10.0, produceTime='2020-11-11', carType='电车'}
Car{id=17, carNum='1333', brand='比亚迪汉', guidePrice=10.0, produceTime='2020-11-11', carType='电车'}
Car{id=18, carNum='1333', brand='比亚迪汉', guidePrice=10.0, produceTime='2020-11-11', carType='电车'}

别名机制:typeAliases

  • 我们之前在XxxxMapper.xml文件书写查询语句,指定返回结果集中数据元素的类型时,每次都需要写全类名,太过于复杂
  • resultType属性用来指定查询结果集的封装类型,这个名字太长
<select id="selectByCarType" resultType="cw.mybatis.pojo.Car"><select/>
<select id="selectAllAscOrDesc" resultType="cw.mybatis.pojo.Car"><select/>
<select id="selectByBrandLike" resultType="cw.mybatis.pojo.Car"><select/>

在核心配置文件中配置别名

  • MyBatis中为我们提供了别名机制,使用别名机制,我们可以为查询语句中指定的返回值类型的全类名取别名
  • 在MyBatis核心配置文件中,在typeAliases标签中使用typeAliase标签起别名
  • 注意:settings标签写在properties标签后,typeAliases标签写在settings标签后
  • typeAliases标签中的typeAlias可以写多个
<!-- 起别名 -->
<typeAliases>
  <!-- 为 cw.mybatis.pojo.Car 起别名,别名为 Car -->
  <typeAlias type="cw.mybatis.pojo.Car" alias="Car"/>
</typeAliases>

在XxxxMapper.xml文件中使用别名

  • 在 CarMapper.xml 文件中使用别名
<select id="selectByCarType" 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 car_type = #{carType}
</select>
  • 测试
@Test
public void test01() {
    SqlSession sqlSession = SqlSessionUtil.openSession();
    // 获取CarMapper接口的代理类对象
    // 底层为CarMapper接口生成了字节码,同时创建了实现类的对象
    CarMapper mapper = sqlSession.getMapper(CarMapper.class);
    List<Car> cars = mapper.selectByCarType("新能源");
    cars.forEach(System.out::println);
    SqlSessionUtil.close();
}

注意点

  • 别名不缺分大小写
<select id="selectByCarType" resultType="caR">

  • namespace不能使用别名机制,必须写全限定接口名称,带有包名的。
<!-- 起别名 -->
<typeAliases>
  <!-- 为 cw.mybatis.pojo.Car 起别名,别名为 Car -->
  <typeAlias type="cw.mybatis.pojo.Car" alias="Car"/>
  <typeAlias type="cw.mybatis.mapper.CarMapper" alias="CarMapper"/>
</typeAliases>
<mapper namespace="CarMapper">

  • typeAlias 标签中的 alias 属性是可以省略的,有默认的别名,省略alias之后,别名就是类的简名,比如:cw.mybatis.pojo.Car 的别名就是 Car/car/cAR/cAr,不区分大小写。
<!-- 起别名 -->
<typeAliases>
  <!-- 为 cw.mybatis.pojo.Car 起别名,别名为 Car -->
  <typeAlias type="cw.mybatis.pojo.Car"/>
</typeAliases>
<select id="selectByCarType" resultType="caR">

别名机制:package

  • 在起别名时,我们可以直接指定要起别名的类所在的包,MyBatis会自动为这个包下的所有的类全部起别名,别名就是类简名,不区分大小写。
<!-- 起别名 -->
<typeAliases>
  <!-- 为 cw.mybatis.pojo 包下面的所有类起别名,别名默认为类的简名 -->
  <package name="cw.mybatis.pojo"/>
</typeAliases>
<select id="selectByCarType" resultType="cAR">

核心配置文件中 mappers 标签的配置

mapper 标签中指定配置文件的三种方式

  • 在MyBatis核心配置文件mappers标签中的mapper标签指定XxxxMapper.xml配置文件位置的方式有三种:
  • <mapper resource="CarMapper.xml"/>
  • 要求类的根路径下必须有:CarMapper.xml
  • 使用 resource 属性指定配置文件的存放位置,这种方式是从类的根路径下开始查找资源。
  • 采用这种方式的话,你的配置文件需要放到类路径当中才行。
  • <mapper url="file:///d:/CarMapper.xml"/>
  • 要求在d:/下有CarMapper.xml文件
  • 使用 url 属性指定配置文件的存放位置,这种方式是一种绝对路径的方式
  • 这种方式不要求配置文件必须放到类路径当中,哪里都行,只要提供一个绝对路径就行。
  • 这种方式使用极少,移植性太差。
  • <mapper class="全限定接口名,带有包名"/>
  • class:该属性的属性值需要我们提供的是 mapper 接口的全限定接口名,必须带有包名的。
  • 使用 class 属性指定全限定接口名,MyBatis就会去该接口所在包下查找与接口相对应与接口同名的 XxxMapper.xml SQL映射配置文件
  • 如:<mapper class="com.powernode.mybatis.mapper.CarMapper"/>,mybatis框架会自动去com/powernode/mybatis/mapper目录下查找CarMapper.xml文件
  • 如果你采用这种方式,那么必须保证CarMapper.xml文件和CarMapper接口必须在同一个目录下,并且名字必须一致。
  • CarMapper接口 -> CarMapper.xml
  • LogMapper接口 -> LogMapper.xml

接口和配置文件的存放目录

  • 将类和配置文件放在同一个目录下,可以采用如下方式建包,因为resources目录相当于类的根路径,就是打包后包的根路径,蓝色的java目录也相当于类的根路径,所以打包完成后 resources 下与 java 下在相同名字的文件夹下的文件会被放在一起
  • 注意:在IDEA的 resources 目录下如果要一次新建多重目录的话,在创建目录时必须采用如下的形式:
  • com/powernode/mybatis/mapper
  • 不能这样采用如下的形式,如下的形式只能用于软件包的创建:
  • com.powernode.mybatis.mapper
  • 如果采用上述的形式,则 com.powernode.mybatis.mapper 这个会被整个当成一个目录名,resources目录下没有建包的概念,只有创建目录的概念

mapper 直接指定接口及配置文件所在的包

  • 采用 mapper 的 class 属性指定接口对应的配置文件的存放位置,可以直接指定接口所在包名,需要使用相应配置文件中的SQL语句时,MyBatis就会去接口所在的包自动查询同名的配置文件
  • 这种方式在实际开发中是使用的,必须满足XML文件必须和接口放在一起,并且名字必须一致。
<mappers>
        <!-- 指定 xml 文件放在 com.powernode.mybatis.mapper 包下 -->
        <package name="com.powernode.mybatis.mapper"/>
    </mappers>


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
2月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
146 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
1月前
|
分布式计算 Java MaxCompute
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 若是设置参数该如何设置
|
2月前
|
搜索推荐 Java 数据库连接
Java|在 IDEA 里自动生成 MyBatis 模板代码
基于 MyBatis 开发的项目,新增数据库表以后,总是需要编写对应的 Entity、Mapper 和 Service 等等 Class 的代码,这些都是重复的工作,我们可以想一些办法来自动生成这些代码。
39 6
|
1月前
|
Java 数据库连接 API
Spring 框架的介绍(Java EE 学习笔记02)
Spring是一个由Rod Johnson开发的轻量级Java SE/EE一站式开源框架,旨在解决Java EE应用中的多种问题。它采用非侵入式设计,通过IoC和AOP技术简化了Java应用的开发流程,降低了组件间的耦合度,支持事务管理和多种框架的无缝集成,极大提升了开发效率和代码质量。Spring 5引入了响应式编程等新特性,进一步增强了框架的功能性和灵活性。
47 0
|
2月前
|
分布式计算 资源调度 Hadoop
大数据-01-基础环境搭建 超详细 Hadoop Java 环境变量 3节点云服务器 2C4G XML 集群配置 HDFS Yarn MapRedece
大数据-01-基础环境搭建 超详细 Hadoop Java 环境变量 3节点云服务器 2C4G XML 集群配置 HDFS Yarn MapRedece
93 4
|
2月前
|
分布式计算 Java Hadoop
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
Hadoop-30 ZooKeeper集群 JavaAPI 客户端 POM Java操作ZK 监听节点 监听数据变化 创建节点 删除节点
70 1
|
3月前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
|
2月前
|
Java 数据安全/隐私保护
java学习笔记(基础习题)
java学习笔记(基础习题)
44 0
|
2月前
|
Java 程序员 开发工具
java学习笔记
java学习笔记
46 0
|
3月前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit