GVKun编程网logo

如何在JDBCTemplates中使用SELECT IN子句?(jdbctemplate执行insert)

20

在这里,我们将给大家分享关于如何在JDBCTemplates中使用SELECTIN子句?的知识,让您更了解jdbctemplate执行insert的本质,同时也会涉及到如何更有效地java–我可以要求

在这里,我们将给大家分享关于如何在JDBCTemplates中使用SELECT IN子句?的知识,让您更了解jdbctemplate执行insert的本质,同时也会涉及到如何更有效地java – 我可以要求JDBCTemplate扩展一个列表参数以在一个in()子句中使用吗?、java – 用于String元素的JdbcTemplate IN子句、JDBC + Spring JDBC(JdbcTemplate)、jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件的内容。

本文目录一览:

如何在JDBCTemplates中使用SELECT IN子句?(jdbctemplate执行insert)

如何在JDBCTemplates中使用SELECT IN子句?(jdbctemplate执行insert)

这是我第一次使用JDBCTemplates,并且遇到了需要使用如下查询的情况:

SELECT * FROM table WHERE field IN (?)

我怎么做?我已经尝试过传递列表/数组值,但是没有成功,我遇到了异常。我当前的代码如下所示:

Long id = getJdbcTemplate().queryForLong(query, new Object[]{fieldIds});

Spring文档指出,除了生成所需数量的“?”之外,没有其他方法可以这样做。占位符以匹配参数List的大小。有解决方法吗?

答案1

小编典典

我认为您不能将其作为单个“?”来完成。与Spring JDBC模板无关,它是核心SQL。

您必须根据需要为其中的任意一个构建一个(?,?,?)。

答案2

小编典典

有一种解决方法使用NamedParameterJdbcTemplate而不是SimpleJdbcDaoSupport,您可以在其中执行以下操作:

List integerList = Arrays.asList(new Integer[] {1, 2, 3});Map<String,Object> params = Collections.singletonMap("fields", integerList);    Long id = namedParameterJdbcTemplate.queryForLong("SELECT * FROM table WHERE field IN (:fields)", params);

但是,这可能会对您在列表中传递的参数数量造成灾难性的限制,具体取决于所使用的DB。

希望这会有所帮助…

java – 我可以要求JDBCTemplate扩展一个列表参数以在一个in()子句中使用吗?

java – 我可以要求JDBCTemplate扩展一个列表参数以在一个in()子句中使用吗?

我可以这样做吗
select * from mytable m where m.group_id in (?)

…并传入一个列表或数组的参数,以扩展到我的参数,即:

select * from mytable m where m.group_id in (1,2,3,4)

具体来说,我使用的是Spring和JdbcTemplate / SimpleJdbcTemplate类.

解决方法

对不起,不能这样做.你可以自己写一个方便的方法,但是据我所知,没有像Hibernate这样的setParameterList().

java – 用于String元素的JdbcTemplate IN子句

java – 用于String元素的JdbcTemplate IN子句

我使用NamedParameterJdbcTemplate for Clause元素,其中一个似乎是List< String>. JdbcTemplate替换它们?,?,?…(列表大小)但是对于带有List< String>的IN子句.它一定要是 ‘?’,’?’….

有没有解决的办法?

解决方法

还有一些其他类似的问题,可能会为您提供有用的答案:

How to execute IN() SQL queries with Spring’s JDBCTemplate effectivly?

为了使这种查询方式在我的最终工作,我必须从普通的旧JDBCTemplate切换到NamedParameterJdbcTemplate.

这是一些示例代码:

String query = "select * from table where columnName in (:listofValues)";
List<String> nameRecordIDs = new ArrayList<String>(); 
// ...
// add values to collection,then
// ...
Map namedParameters = Collections.singletonMap("listofValues",nameRecordIDs);
namedparameterJdbcTemplate.query(query,namedParameters,new MyMapper());

JDBC + Spring JDBC(JdbcTemplate)

JDBC + Spring JDBC(JdbcTemplate)

1. JDBC
-- JDBC (Java Database Connectivity) java数据库连接,是java标准库的一部分,主要负责处理对数据库的访问
(纯JDBC代码来访问数据库)
--了解java.sql包中几个对象
a. DriverManager :实用工具类,认识所有可用的数据库驱动程序
b. Connection:代表与数据库的连接,包含url, 用户名,密码等信息,可使用DriverManager来创建他们
c. PreparedStatement 和 CallableStatement:把真实的sql语句发送给数据库服务器。sql语句从Connection创建的
d. esultSet:数据返回方式,可迭代,每个对象代表一行,可使用getFoo(index) / getFoo(name)方法访问数据,其中Foo是数据类型,如String,Int等,index是列号(1开始),name是列名,ResultSet由sql语句返回
e. Date, Time, Timestamp:时间数据的sql表示形式
--java.sql.sqlException: No suitable driver 问题解决
解决办法是将MysqL的驱动jar包mysql-connector-java-8.0.28.jar,放到C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext (针对本机)

@Test
public void testjdbc() throws sqlException {
String url = "jdbc:MysqL://192.168.0.10:3306/agiletc";
Connection conn = DriverManager.getConnection(url,"steve","appleseed");
String sql = "select id,username,password from user";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while(rs.next()){
Integer id = rs.getInt("id");
String name = rs.getString("username");
String password = rs.getString("password");
String msg = String.format("ID: %d, Name: %s, Pwd:%s",id,name,password);
System.out.println(msg);
}
}

2.数据库框架 Spring JDBC--JdbcTemplate
--Spring框架提供很多操作模板类,如操作关系型数据的JdbcTemplate和HibernateTemplate,操作nosql数据库的Redistemplate,操作消息队列的jmstemplate等等
--JdbcTemplate类是最基本的Spring JDBC模板,无需使用纯JDBC也能执行sql语句
--JdbcTemplate受Datasource支持,线程安全,意味着可在整个应用程序中使用同一个实例
--JdbcTemplate流程步骤
a. 导入相关依赖
b. 创建数据库表和实体类
(Entity类:
1.实体类的作用是和数据表做映射,即数据库中的一个表映射成对应的一个java类,其中还有一个映射文件
2.属性对应数据表中的字段, 方法即是对表中数据的操作(setter和getter方法,带参数的构造器和无参数的构造器,重写父类的方法等)
c. 创建JdbcTemplate对象
d. 执行数据库操作
--实操例子
(1)导入相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>MysqL</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
(2)MysqL建表
CREATE TABLE account(
`oid` int NOT NULL AUTO_INCREMENT ,
`username` VARCHAR(10) NOT NULL,
`money` int NOT NULL,
PRIMARY KEY(`oid`)
);
(3)创建Entity类
public class Account {
private int oid;
private String username;
private int money;

public int getoid(){
return oid;
}
public void setoid(int oid){
this.oid = oid;
}
public String getUsername(){
return username;
}
public void setUsername(String username){
this.username = username;
}
public int getMoney(){
return money;
}
public void setMoney(int money){
this.money = money;
}
@Override
public String toString(){
return "Account{" + "oid=" + oid + " ,username=" + username + '\'' + ", money=" + money + "}";
}
}
(4)创建JdbcTemplate对象,执行数据库操作
@Test
public void test1() throws PropertyVetoException {
//创建c3p0数据库连接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//设置连接参数
dataSource.setDriverClass("com.MysqL.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:MysqL://localhost:3306/testing");
dataSource.setUser("root");
dataSource.setPassword("password");
//创建jdbcTemplate对象
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//给jdbcTemplate对象设置数据源
jdbcTemplate.setDataSource(dataSource);
//插入一条数据
int i = jdbcTemplate.update("insert into account values(?,?,?)",3,"Jhon",1500);
System.out.println(i);
}

--代码优化
(1)jdbc.properties
jdbc.driver=com.MysqL.jdbc.Driver
jdbc.url=jdbc:MysqL://localhost:3306/testing
jdbc.user=root
jdbc.password=password

(2)spring-jdbc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!--引入jdbc.properties-->
<context:property-placeholder location="jdbc.properties"/>
<!--配置c3p0连接池-->
<bean id="dataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--配置jdbcTemplate-->
<bean id="jdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>

(3)applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<import resource="classpath:spring-jdbc.xml"/>
</beans>

(4)测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(value = "classpath:applicationContext.xml")
public class TestJdbcTemplate {

@Autowired
private JdbcTemplate jdbcTemplate;

//Spring创建jdbcTemplate对象
@Test
public void test2() {
//插入一条数据
int i = jdbcTemplate.update("insert into account values(?,?,?)", 3, "lucy", 5000);
System.out.println(i);
}
}

--JdbcTemplate常用操作(CURD操作)
注意:
a. 如果pojo中没有get/set,那么Springjdbc映射时会找不到属性值,从而为null
b. BeanPropertyRowMapper是RowMapper的实现类
public class BeanPropertyRowMapper<T> implements RowMapper<T>
(1)代码
@Test
public void test3() {
int i = 0;
//插入一条数据
i = jdbcTemplate.update("insert into account values(?,?,?)", 5, "Amy", 5000);
System.out.println("insert:" + i);
//更新操作
i = jdbcTemplate.update("update account set money=? where username =?", 000, "tom");
System.out.println("update:" + i);
//删除操作
i = jdbcTemplate.update("delete from account where oid = ?", 4);
System.out.println("delete:" + i);
//查询全部
List<Account> accounts = jdbcTemplate.query("select * from account",
new BeanPropertyRowMapper<Account>(Account.class));
AtomicInteger j = new AtomicInteger(1);
accounts.forEach((s) -> {
System.out.println("第" + (j.getAndIncrement()) + "条:" + s);
});
//查询单个
Account account = jdbcTemplate.queryForObject("select * from account where username = ?",
new BeanPropertyRowMapper<Account>(Account.class),"lucy");
System.out.println("查询单个" + account);

}

jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件

jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件

jdbc-plus简介

jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件。项目地址: https://github.com/deeround/jdbc-plus

特性:

  • 使用简单,对代码入侵很小
  • 可自定义任意扩展插件
  • 多租户参考mybatis-plus多租户的实现原理,理论上与mybatis-plus多租户插件支持度一样
  • 分页参考PageHelper的实现原理,使用简单,对代码入侵较小,还可以注册不支持的数据库
  • 免费开源,可任意使用修改代码

快速开始

  1. 引入jdbc-plus-spring-boot-starter
<dependency>
    <groupId>com.github.deeround</groupId>
    <artifactId>jdbc-plus-spring-boot-starter</artifactId>
    <version>${version}</version>
</dependency>
  1. 注入需要使用的插件
[@Configuration](https://my.oschina.net/pointdance)
public class JdbcPlusConfig {

    /**
     * PaginationInterceptor是内置的分页插件(分页插件一定要注入在TenantLineHandler之后,可以通过Order来控制顺序)
     */
    [@Bean](https://my.oschina.net/bean)
    @Order(9)
    public IInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    /**
     * TenantLineHandler是内置的多租户插件插件
     */
    [@Bean](https://my.oschina.net/bean)
    @Order(1)
    public IInterceptor tenantLineInterceptor() {
        return new TenantLineInterceptor(new TenantLineHandler() {
            /**
             * 当前租户ID
             */
            @Override
            public Expression getTenantId() {
                String currentTenantId = "test_tenant_1";//可以从请求上下文中获取(cookie、session、header等)
                return new StringValue(currentTenantId);
            }

            /**
             * 租户字段名
             */
            @Override
            public String getTenantIdColumn() {
                return "tenant_id";
            }

            /**
             * 根据表名判断是否忽略拼接多租户条件
             */
            @Override
            public boolean ignoreTable(String tableName) {
                return TenantLineHandler.super.ignoreTable(tableName);
            }
        });
    }
}

多租户插件

  1. 注入多租户插件
    /**
     * TenantLineHandler是内置的多租户插件插件
     */
    @Bean
    @Order(1)
    public IInterceptor tenantLineInterceptor() {
        return new TenantLineInterceptor(new TenantLineHandler() {
            /**
             * 当前租户ID
             */
            @Override
            public Expression getTenantId() {
                String currentTenantId = "test_tenant_1";//可以从请求上下文中获取(cookie、session、header等)
                return new StringValue(currentTenantId);
            }

            /**
             * 租户字段名
             */
            @Override
            public String getTenantIdColumn() {
                return "tenant_id";
            }

            /**
             * 根据表名判断是否忽略拼接多租户条件
             */
            @Override
            public boolean ignoreTable(String tableName) {
                return TenantLineHandler.super.ignoreTable(tableName);
            }
        });
    }
  1. service层执行SQL时自动添加租户字段
    @Autowired
    JdbcTemplate jdbcTemplate;

    public void insert() {
        this.jdbcTemplate.update("insert into test_user(id,name) values(''1'',''wangwu'')");
        //最终执行SQL:insert into test_user(id,name,tenant_id) values(''1'',''wangwu'',''test_tenant_1'')
    }

    public void delete() {
        this.jdbcTemplate.update("delete from test_user");
        //最终执行SQL:delete from test_user where tenant_id=''test_tenant_1''
    }

    public void update() {
        this.jdbcTemplate.update("update test_user set name=''lisi'' where id=''1''");
        //最终执行SQL:update test_user set name=''lisi'' where id=''1'' and tenant_id=''test_tenant_1''
    }

    public List<Map<String, Object>> query() {
        return this.jdbcTemplate.queryForList("select * from test_user");
        //最终执行SQL:select * from test_user where tenant_id=''test_tenant_1''
    }

分页插件

  1. 注入分页插件
    /**
     * PaginationInterceptor是内置的分页插件(分页插件一定要注入在TenantLineHandler之后,可以通过Order来控制顺序)
     */
    @Bean
    @Order(9)
    public IInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
  1. service层执行SQL时自动对SQL进行分页查询
    @Autowired
    JdbcTemplate jdbcTemplate;

    public PageInfo<Map<String, Object>> page1() {
        PageHelper.startPage(1, 2);
        List<Map<String, Object>> list = this.jdbcTemplate.queryForList("select * from test_user");//最终执行SQL:select * from test_user LIMIT 0,2
        PageInfo<Map<String, Object>> page = new PageInfo<>(list);//PageInfo对象包含了分页信息(总行数等)
        return page;
    }

    public PageInfo<Map<String, Object>> page2() {
        PageHelper.startPage(2, 2);
        List<Map<String, Object>> list = this.jdbcTemplate.queryForList("select * from test_user");//最终执行SQL:select * from test_user LIMIT 2,2
        PageInfo<Map<String, Object>> page = new PageInfo<>(list);//PageInfo对象包含了分页信息(总行数等)
        return page;
    }
  1. 自定义分页

当插件不支持的数据库分页,可以通过PageHelper.registerDialectAlias(String alias, Class clazz) 注册一个自己分页实现类即可,也可以覆盖已支持的数据库分页。

自定义插件

示例:写一个打印SQL语句、执行参数、以及执行SQL耗时的监控插件。

  1. 编写MyStatInterceptor插件
/**
 * SQL监控插件
 */
@Slf4j
public class MyStatInterceptor implements IInterceptor {
    /**
     * 自定义插件是否支持
     */
    @Override
    public boolean supportMethod(final MethodInvocationInfo methodInfo) {
        return IInterceptor.super.supportMethod(methodInfo);
    }

    /**
     * SQL执行前方法(主要用于对SQL进行修改)
     */
    @Override
    public void beforePrepare(final MethodInvocationInfo methodInfo, JdbcTemplate jdbcTemplate) {
        log.info("原始SQL:{}", methodInfo.getSql());
        log.info("入参:{}", Arrays.toString(methodInfo.getArgs()));
        log.info("执行SQL开始时间:{}", LocalDateTime.now());
        methodInfo.getUserAttributes().put("startTime", LocalDateTime.now());
    }

    /**
     * SQL执行完成后方法(主要用于对返回值修改)
     *
     * @param result 原始返回对象
     * @return 处理后的返回对象
     */
    @Override
    public Object beforeFinish(Object result, final MethodInvocationInfo methodInfo, JdbcTemplate jdbcTemplate) {
        log.info("执行SQL结束时间:{}", LocalDateTime.now());
        LocalDateTime startTime = (LocalDateTime) methodInfo.getUserAttributes().get("startTime");
        log.info("执行SQL耗时:{}毫秒", Duration.between(startTime, LocalDateTime.now()).toMillis());
        return result;
    }
}
  1. 注入自定义插件
    /**
     * 自定义插件注入,注入位置按实际情况
     */
    @Bean
    @Order(0)
    public IInterceptor myStatInterceptor() {
        return new MyStatInterceptor();
    }
  1. 查看效果(查看打印日志)
c.g.d.j.p.s.config.MyStatInterceptor     : 原始SQL:select * from test_user
c.g.d.j.p.s.config.MyStatInterceptor     : 入参:[select * from test_user]
c.g.d.j.p.s.config.MyStatInterceptor     : 执行SQL开始时间:2023-04-23T16:35:58.151
c.g.d.j.p.s.config.MyStatInterceptor     : 执行SQL结束时间:2023-04-23T16:35:58.655
c.g.d.j.p.s.config.MyStatInterceptor     : 执行SQL耗时:503毫秒

★ 鸣谢 ★

https://github.com/baomidou/mybatis-plus

https://github.com/pagehelper/Mybatis-PageHelper

https://github.com/deeround/jdbc-plus

今天的关于如何在JDBCTemplates中使用SELECT IN子句?jdbctemplate执行insert的分享已经结束,谢谢您的关注,如果想了解更多关于java – 我可以要求JDBCTemplate扩展一个列表参数以在一个in()子句中使用吗?、java – 用于String元素的JdbcTemplate IN子句、JDBC + Spring JDBC(JdbcTemplate)、jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件的相关知识,请在本站进行查询。

本文标签: