java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > mybatis动态生成sql语句

mybatis动态生成sql语句的实现示例

作者:代码代码快快显灵

在MyBatis中,动态SQL是一个非常重要的特性,它允许我们根据条件动态地生成SQL语句,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

在 Java 编程中,我们常常需要将数据传递给 SQL 查询,特别是在动态生成 SQL 语句时,通常会用到 Map 这种集合类。Map 可以将多个键值对传递给 SQL 语句的占位符,完成动态参数绑定的功能。我们下面详细讲解图中的知识点。

1. Map 的基本用法

Map 是 Java 集合框架中的一种数据结构,它以键值对 (key-value) 的形式存储数据。Map 中的键唯一且不能重复,而值可以重复。常用的实现类包括 HashMapTreeMap 等。

示例代码

Map<String, Object> map = new HashMap<>();
map.put("k1", "1111");
map.put("k2", "比亚迪汉");
map.put("k3", 10.0);
map.put("k4", "2020-11-11");
map.put("k5", "电车");

这里我们创建了一个 HashMap,并通过 put 方法将一些数据存入 Map。键是 String 类型,值是 Object 类型,意味着可以存放不同类型的数据(如字符串、数字、日期等)。

2. 占位符 #{} 的使用

在执行 SQL 语句时,为了防止 SQL 注入和简化代码,我们经常使用占位符将 SQL 参数动态地传入。( ? 是 JDBC 中的占位符,用于预编译 SQL 语句中的参数。在使用 JDBC 时,SQL 语句通常是预编译的,? 用于表示一个位置,在执行时由具体的参数替换。占位符 #{} 这一语法主要用于一些持久化框架,如 MyBatis。

SQL 语句示例

insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) 
values(null, #{k1}, #{k2}, #{k3}, #{k4}, #{k5});

在这个 SQL 语句中,#{k1}#{k2} 等占位符将会在运行时被替换为 Map 中对应的值。框架会根据占位符的键来查找 Map 中的值并动态替换。如果键不存在,则返回 null这个语句通常配置在通常用于 MyBatis 的 SQL 映射的XML文件中

注意

3. Map 键名与数据库字段名的对应关系

为了使代码更加易读、维护更加方便,我们通常建议将 Map 中的键名与数据库字段名保持一致。这样一来,不仅能够直观地映射参数,还能避免因键名不统一而导致的问题。

map.put("carNum", "1111");
map.put("brand", "比亚迪汉2");
map.put("guidePrice", 10.0);
map.put("produceTime", "2020-11-11");
map.put("carType", "电车");

在这个例子中,我们将 Map 的键名改为 carNumbrand 等,和数据库表的列名一致。这样一来,代码就更容易理解和维护。

SQL 语句

insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) 
values(null, #{carNum}, #{brand}, #{guidePrice}, #{produceTime}, #{carType});

POJO 类实现动态传参

1. POJO 类与 SQL 占位符传递

POJO(Plain Old Java Object) 是指普通的 Java 对象,通常用作数据传输对象。在 Java 应用中,我们可以通过 POJO 类的属性来传递 SQL 语句中的参数。

Car car = new Car(null, "3333", "比亚迪秦", 30.0, "2020-11-11", "新能源");

在这个例子中,Car 是一个 POJO 类,包含一些车辆信息的属性。通过实例化这个类,我们可以将具体的值传入到 SQL 语句中的占位符。

2. 占位符 #{} 的使用

在 MyBatis 等持久化框架中,使用占位符 #{} 来表示将 POJO 的属性值注入到 SQL 语句中。大括号 {} 里面填写的内容是 POJO 类的属性名(严格意义上来说:如果使用P0J0对象传递值的话,这个{}里面写的是get方法的方法名去掉get,然后将剩下的单词首字母小写,然后放进去。

SQL 语句示例

insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) 
values(null, #{carNum}, #{brand}, #{guidePrice}, #{produceTime}, #{carType});

3. 占位符与属性对应的规则

MyBatis 会自动根据 POJO 类中的属性名来查找对应的 getter 方法。如果 POJO 类中没有提供对应的 getter 方法,则会报错。

错误示例

There is no getter for property named 'xyz' in 'class com.powernode.mybatis.pojo.Car'

这是因为 MyBatis 尝试通过 getXyz() 方法来获取 xyz 属性的值,但 POJO 类中没有定义这个方法。为了避免这种错误,我们需要在 POJO 类中提供每个属性的 getter 和 setter 方法。

4. 如何解决没有 getter 方法的问题?

如果遇到没有对应 getter 方法的情况,可以通过在 POJO 类中手动添加相应的 getter 方法来解决。比如:

public String getXyz() {
    return xyz;
}

5. 占位符 #{} 的使用规则

通过这个错误示例,我们可以总结出占位符的使用规则:MyBatis 是通过反射机制来调用 getter 方法。也就是说,在 #{} 占位符中写的内容(如 #{carNum})并不直接对应 POJO 的属性名,而是对应属性的 getter 方法。

规则

占位符 #{} 中的内容确实是与 POJO 类的属性相关,但 MyBatis 实际上是通过 调用 POJO 类的 getter 方法 来获取这些值的,而不是直接访问属性本身。因此,为了确保 MyBatis 能正确地映射 SQL 参数,POJO 类中的 getter 方法必须与占位符中的名字相匹配。 

删除DELETE操作:

 1. 删除操作的实现

int count = sqlSession.delete("deleteById", 59);

这行代码展示了通过 sqlSession.delete() 方法来执行删除操作,其中:

2. MyBatis Mapper 文件中的SQL语句 

<delete id="deleteById">
    delete from t_car where id = #{fdsfd}
</delete>

这是在MyBatis的Mapper XML文件中定义的删除操作,具体解释如下:

3. 占位符的说明

注意:如果占位符只有一个,那么 #{} 的大括号里可以随意。但是最好见名知意。

这里说明了 #{} 是MyBatis的占位符,用于绑定参数。虽然在某些情况下可以随意使用参数名(如 fdsfd),但是为了代码的可读性和维护性,建议使用有意义的名称,比如 id

例如,改为:

<delete id="deleteById">
    delete from t_car where id = #{id}
</delete>

这样更直观,容易理解。

4. 整体流程总结

更新操作:

1. 更新操作的SQL语句

<update id="updateById">
    update t_car set
        car_num=#{carNum},
        brand=#{brand},
        guide_price=#{guidePrice},
        produce_time=#{produceTime},
        car_type=#{carType}
    where
        id = #{id}
</update>

这是在MyBatis的Mapper XML文件中定义的更新操作。解释如下:

这里使用 #{} 作为MyBatis的占位符,类似于之前的删除操作。它会在执行时将参数替换为实际值。具体字段说明:

2. Java代码中的更新操作

Car car = new Car(4L, "9999", "凯美瑞", 30.3, "1999-11-10", "燃油车");
int count = sqlSession.update("updateById", car);

这里通过 new Car() 创建了一辆 Car 对象,包含了所有要更新的属性。各个属性与Mapper XML中的占位符对应。

然后调用 sqlSession.update("updateById", car); 进行更新操作。MyBatis会将 car 对象的属性传递给对应的SQL语句中的占位符,生成最终的SQL语句并执行更新。

3. 详细流程说明

MyBatis会根据Java代码中的 car 对象的属性,替换Mapper XML中的占位符,生成最终的SQL语句。

假设 car 对象的 id 是4,那么生成的SQL语句大致如下

update t_car set
    car_num='9999',
    brand='凯美瑞',
    guide_price=30.3,
    produce_time='1999-11-10',
    car_type='燃油车'
where
    id = 4;

执行这条SQL语句后,t_car 表中 id 为4的记录就会被更新成新值。

更新后,sqlSession.update() 方法会返回受影响的行数,即 count

select查找操作 

1. MyBatis 中的 select 标签

作用:MyBatis 使用 select 标签来编写 SQL 查询语句,定义如何从数据库中获取数据。在这个例子中,它用于根据 id 字段查询 t_car 表中的记录。

SQL 语句解释

<select id="selectById" resultType="com.powernode.mybatis.pojo.Car">
    select * from t_car where id = #{id}
</select>

id 属性id="selectById" 是一个唯一标识符,表示这条 SQL 语句在 MyBatis 配置中的 ID。当你在代码中调用 sqlSession.selectOne("selectById", 参数) 时,MyBatis 会根据这个 ID 找到对应的 SQL 语句。

SQL 查询select * from t_car where id = #{id} 是实际的 SQL 语句。#{id} 是 MyBatis 的动态 SQL 占位符,它会在运行时将你传入的参数(比如 1)替换为实际的查询条件。

2. resultType 属性

作用resultType 属性告诉 MyBatis 查询结果应该映射成什么样的 Java 对象。也就是说,当从数据库中获取到数据后,MyBatis 会根据 resultType 中指定的类型来创建该类型的对象,并将查询结果封装到这个对象中。

在此例子中的使用

resultType="com.powernode.mybatis.pojo.Car"

这里 resultType="com.powernode.mybatis.pojo.Car" 指定了 Car 类为查询结果的映射对象类型。即查询到的 t_car 表中的记录会被封装成 Car 类的实例。

全限定类名:com.powernode.mybatis.pojo.Car 是 Car 类的全限定类名,即包括了包名和类名。这是 MyBatis 推荐的写法,因为这样可以确保避免类名冲突,并确保 MyBatis 能找到正确的类。

resultType 的作用机制

查询结果(即数据库中的一条记录)会被转换为 Java 对象。MyBatis 会根据数据库表中的列名与 Car 类的属性名进行匹配,如果列名与属性名相同,MyBatis 就会自动将查询结果中的列值赋给对应的属性。

例如:假设 t_car 表有以下列:

注意事项

如果数据库中的列名和 Java 类中的属性名不一致,你需要使用别名(AS)或者 resultMap 进行手动映射。

1. 假设的数据库表 t_car

CREATE TABLE t_car (
    car_id INT PRIMARY KEY,
    car_name VARCHAR(50),
    car_brand VARCHAR(50)
);

在这个表中,列名是 car_idcar_name, 和 car_brand

Java 类 Car

public class Car {
    private int id;
    private String name;
    private String brand;

    // Getters and setters
    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
}

在 Java 类 Car 中,属性名分别是 idname, 和 brand,显然与数据库表 t_car 的列名不一致。

解决办法:使用 resultMap 进行手动映射

由于列名和属性名不一致,直接使用 resultType 是无法自动映射的,这时我们可以使用 resultMap 进行手动映射。

3. MyBatis 映射配置:起别名

<select id="selectById" resultType="com.powernode.mybatis.pojo.Car">
    select car_id as id, car_name as name, car_brand as brand
    from t_car
    where car_id = #{id}
</select>

在这个配置中:

SQL 查询select * from t_car where car_id = #{id},通过 #{id} 来传递 Java 方法中的参数。

这样,通过使用 AS 设置别名,可以直接在 SQL 语句中将数据库的列名与 Java 类的属性名进行对应,而无需修改数据库或 Java 类。

3. selectOne 方法

作用selectOne 是 MyBatis 提供的一个方法,用于执行返回单条记录的查询。当我们确定查询的结果是唯一的(例如,查询主键),可以使用这个方法。如果查询结果返回多条记录,MyBatis 会抛出异常(TooManyResultsException)。

用法解释

Car car = sqlSession.selectOne("selectById", 1);

sqlSession 是 MyBatis 中操作数据库的会话对象,类似于 JDBC 中的 Connection 对象。

selectOne("selectById", 1):调用了 selectById 这个 SQL 查询,并传递了参数 1。这个 1 会替换 SQL 中的 #{id} 占位符,最终执行的 SQL 会是:

select * from t_car where id = 1;

返回的结果会是一个 Car 对象,存储在变量 car 中。

 select查所有的数据

sql语句

<select id="selectAll" resultType="com.powernode.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
</select>

在这个查询中,使用了别名将数据库表中的列名映射到 Java 类 Car 中的属性名:

Java 代码中的 selectList 调用 

List<Car> cars = sqlSession.selectList("selectAll");

注意事项

到此这篇关于mybatis动态生成sql语句的实现示例的文章就介绍到这了,更多相关mybatis动态生成sql语句内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文