1.主要思想
动态SQL的主要思想是根据不同的需求和条件生成可变的SQL语句,以满足动态性和灵活性的需求。这样可以根据不同的情况生成不同的SQL查询、插入、更新或删除语句。
动态SQL通常使用字符串拼接、字符串格式化或参数绑定等技术来生成SQL语句。它允许在运行时根据特定条件生成不同的查询条件、表名、列名、排序方式等,以满足动态变化的需求。
2.应用场景:
动态SQL是一种在程序运行时根据条件或参数的不同生成和执行SQL语句的方法。它与静态SQL相对,静态SQL是在编译时就确定好的固定SQL语句。
动态SQL的应用场景非常广泛,包括但不限于搜索和过滤功能、数据分页、动态排序、动态表名和列名、动态插入和更新等。
需要注意的是,在使用动态SQL时,应该遵循良好的编程实践,特别是对输入参数进行适当的验证和处理,以防止潜在的安全风险,如SQL注入攻击。
-
搜索和过滤:动态SQL可以用于构建灵活的搜索和过滤功能,用户可以根据不同的条件查询数据。例如,一个电子商务网站可以根据用户选择的不同筛选条件生成相应的SQL查询语句来获取符合要求的商品列表。
-
数据分页:动态SQL可用于实现数据分页功能。通过动态生成包含LIMIT或OFFSET子句的SQL语句,可以根据用户请求返回指定范围的数据结果,以提高系统性能和用户体验。
-
动态排序:使用动态SQL可以根据用户的排序要求生成不同的ORDER BY子句,以实现动态排序功能。用户可以根据需要选择不同的字段和排序方式进行排序操作。
-
动态表名和列名:有时需要在查询中根据不同的条件或环境选择不同的表名或列名。动态SQL可以根据条件生成包含动态表名和列名的查询语句,以适应不同的数据结构或数据库设计。
-
动态插入和更新:动态SQL还可以用于根据用户输入或系统条件生成插入和更新语句。这在需要根据不同情况动态生成数据操作语句的应用中非常有用。
3.代码实现
数据库:student表
实体类:Student.java
(对应数据库表重大字段)
package com.xiaoma.po;
import java.util.Date;
public class Student {
private int sno;
private String sname;
private String sgender;
private Date sbirthday;
public Student() {
}
public Student(int sno, String sname, String sgender, Date sbirthday) {
this.sno = sno;
this.sname = sname;
this.sgender = sgender;
this.sbirthday = sbirthday;
}
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getSgender() {
return sgender;
}
public void setSgender(String sgender) {
this.sgender = sgender;
}
public Date getSbirthday() {
return sbirthday;
}
public void setSbirthday(Date sbirthday) {
this.sbirthday = sbirthday;
}
@Override
public String toString() {
return "Student{" +
"sno=" + sno +
", sname='" + sname + '\'' +
", sgender='" + sgender + '\'' +
", sbirthday=" + sbirthday +
'}';
}
}
QueryVO.java
(用户从前端传来的各种各样的参数组合)
package com.xiaoma.vo;
import com.xiaoma.po.Product;
import com.xiaoma.po.Student;
import java.util.List;
public class QueryVO {
private Product product;
private Student student;
private List<Integer> snos;
public QueryVO() {
}
public QueryVO(Product product) {
this.product = product;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public List<Integer> getSnos() {
return snos;
}
public void setSnos(List<Integer> snos) {
this.snos = snos;
}
@Override
public String toString() {
return "QueryVO{" +
"product=" + product +
", student=" + student +
", snos=" + snos +
'}';
}
}
StudentMapper.java
(定义接口和接口中的方法,无需编写具体实现类,实现由Mybatis框架自动完成)
package com.xiaoma.mapper;
import com.xiaoma.po.Student;
import com.xiaoma.vo.QueryVO;
import java.util.List;
public interface StudentMapper {
/**
*
* @param queryVO 封装着学生相关的查询信息
* @return 根据条件查询到的学生信息
*/
List<Student> selectByCondition(QueryVO queryVO);
/**
* 根据多个学号查询结果
* @param queryVO 封装着任意多个学号
* @return 满足任意个学号的结果都返回
*/
List<Student> selectBySnos(QueryVO queryVO);
}
StudentMapper.xml
(id对应StudentMapper中的方法名)
<?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="com.xiaoma.mapper.StudentMapper">
<select id="selectByCondition" parameterType="com.xiaoma.vo.QueryVO" resultType="com.xiaoma.po.Student">
SELECT * FROM mybatis.student
<!-- WHERE sname LIKE #{student.sname} AND sgender = #{student.sgender}-->
<where>
<if test="student != null">
<!--sname不为空,此时才去拼接到where语句中-->
<if test="student.sname != null and student.sname != ''">
AND sname LIKE #{student.sname}
</if>
<if test="student.sgender != null and student.sgender != ''">
AND sgender = #{student.sgender}
</if>
</if>
</where>
</select>
<select id="selectBySnos" parameterType="com.xiaoma.vo.QueryVO" resultType="com.xiaoma.po.Student">
SELECT * FROM mybatis.student
<!--WHERE sno IN (1,2,3)-->
<where>
<if test="snos!=null and snos.size()>0">
sno in
<foreach collection="snos" item="sno" open="(" close=")" separator=",">
#{sno}
</foreach>
</if>
</where>
</select>
</mapper>
测试类:StudentMapperTest.java
package com.xiaoma.mapper;
import com.xiaoma.po.Student;
import com.xiaoma.vo.QueryVO;
import junit.framework.TestCase;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
public class StudentMapperTest extends TestCase {
SqlSessionFactory sqlSessionFactory;
public void setUp() throws Exception {
//加载全局配置文件
InputStream is = StudentMapperTest.class.getClassLoader().getResourceAsStream("sqlMapConfig.xml");
//根据全局配置文件创建sqlSessionFactory工厂
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
}
public void tearDown() throws Exception {
}
@Test
public void testSelectByCondition() {
QueryVO queryVO = new QueryVO();
Student student = new Student();
// student.setSname("张三");
student.setSgender("男");
queryVO.setStudent(student);
sqlSessionFactory.openSession()
.getMapper(StudentMapper.class)
.selectByCondition(queryVO)
.forEach(System.out::println);
}
@Test
public void testSelectBySnos() {
QueryVO queryVO = new QueryVO();
List<Integer> snos = Arrays.asList(1,2,3);
queryVO.setSnos(snos);
sqlSessionFactory.openSession()
.getMapper(StudentMapper.class)
.selectBySnos(queryVO)
.forEach(System.out::println);
}
}
4.运行结果