在这里,我们将给大家分享关于如何在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)
- java – 我可以要求JDBCTemplate扩展一个列表参数以在一个in()子句中使用吗?
- java – 用于String元素的JdbcTemplate IN子句
- JDBC + Spring JDBC(JdbcTemplate)
- jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件
如何在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()子句中使用吗?
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类.
解决方法
java – 用于String元素的JdbcTemplate 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)
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简介
jdbc-plus是一款基于JdbcTemplate增强工具包, 基于JdbcTemplate已实现分页、多租户等插件,可自定义扩展插件。项目地址: https://github.com/deeround/jdbc-plus
特性:
- 使用简单,对代码入侵很小
- 可自定义任意扩展插件
- 多租户参考mybatis-plus多租户的实现原理,理论上与mybatis-plus多租户插件支持度一样
- 分页参考PageHelper的实现原理,使用简单,对代码入侵较小,还可以注册不支持的数据库
- 免费开源,可任意使用修改代码
快速开始
- 引入jdbc-plus-spring-boot-starter
<dependency>
<groupId>com.github.deeround</groupId>
<artifactId>jdbc-plus-spring-boot-starter</artifactId>
<version>${version}</version>
</dependency>
- 注入需要使用的插件
[@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);
}
});
}
}
多租户插件
- 注入多租户插件
/**
* 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);
}
});
}
- 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''
}
分页插件
- 注入分页插件
/**
* PaginationInterceptor是内置的分页插件(分页插件一定要注入在TenantLineHandler之后,可以通过Order来控制顺序)
*/
@Bean
@Order(9)
public IInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
- 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;
}
- 自定义分页
当插件不支持的数据库分页,可以通过PageHelper.registerDialectAlias(String alias, Class clazz)
注册一个自己分页实现类即可,也可以覆盖已支持的数据库分页。
自定义插件
示例:写一个打印SQL语句、执行参数、以及执行SQL耗时的监控插件。
- 编写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;
}
}
- 注入自定义插件
/**
* 自定义插件注入,注入位置按实际情况
*/
@Bean
@Order(0)
public IInterceptor myStatInterceptor() {
return new MyStatInterceptor();
}
- 查看效果(查看打印日志)
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已实现分页、多租户等插件,可自定义扩展插件的相关知识,请在本站进行查询。
本文标签: