mybatis 适配gbase8s中批量插入问题

近期在某项目中在使用mybatis 的foeach标签向gbase8s数据库插入数据库报错

Caused by: java.sql.SQLException: 主变量号无效。
    at com.gbasedbt.util.IfxErrMsg.getSQLException(IfxErrMsg.java:409)
    at com.gbasedbt.jdbc.IfxSqli.a(IfxSqli.java:3576)
    at com.gbasedbt.jdbc.IfxSqli.D(IfxSqli.java:3856)
    at com.gbasedbt.jdbc.IfxSqli.dispatchMsg(IfxSqli.java:2746)
    at com.gbasedbt.jdbc.IfxSqli.receiveMessage(IfxSqli.java:2671)
    at com.gbasedbt.jdbc.IfxSqli.executePrepare(IfxSqli.java:1292)
    at com.gbasedbt.jdbc.IfxPreparedStatement.f(IfxPreparedStatement.java:490)
    at com.gbasedbt.jdbc.IfxPreparedStatement.a(IfxPreparedStatement.java:471)
    at com.gbasedbt.jdbc.IfxPreparedStatement.<init>(IfxPreparedStatement.java:273)
    at com.gbasedbt.jdbc.IfxSqliConnect.h(IfxSqliConnect.java:6348)
    at com.gbasedbt.jdbc.IfxSqliConnect.prepareStatement(IfxSqliConnect.java:2552)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.ibatis.datasource.pooled.PooledConnection.invoke(PooledConnection.java:255)
    at com.sun.proxy.$Proxy7.prepareStatement(Unknown Source)
...

其原因为在使用 foreach 标签做数据插入时,本质是将集合中的数据拼接成一个大sql,如果sql中使用了#{},则超出 32765 报错主机变量不足,oracle 的上限为65535,mysql中 当整体 sql长度超出范围后一样会报错

解决方案

1减少一次传入集合的数量,保证整体sql 绑定变量不超过32765

2使用 ${}代替#{}

3使用mybatis 推荐的ExecutorType.BATCH 方式去批量插入

        InputStream inputStream = Resources.getResourceAsStream(resource);
        sf = new SqlSessionFactoryBuilder().build(inputStream);
        sqlsession = sf.openSession(ExecutorType.BATCH);
        TableOneMapper tableOneMapper = sqlsession.getMapper(TableOneMapper.class);
        List<TableTwo> list =new ArrayList<>();
        for (int i=1;i<= 20000;i++){
            list.add(new TableTwo(i, UUID.randomUUID().toString(),UUID.randomUUID().toString()));
        }
        list.stream().forEach(tableTwo -> tableOneMapper.instTab3(tableTwo));
        sqlsession.commit();
        sqlsession.close();

在 gbase8s 某些版本中,使用foreach 标签做插入时不支持 byte,text,clob,blob,若使用方案3 则没有问题,并且ExecutorType.BATCH 的效率要远远高于其他方式

因为ExecutorType.BATCH 底层使用的是PreparedStatement.addBatch(),先将部分数据缓存起来,一起批量提交,极大的减少了客户端与数据库的交互

从数据库协议中观察不难发现

使用ExecutorType.BATCH 时 只做一次PREPARE,多次 SQ_BIND,并且返回结果也是批量一起返回,而不使用批量插入则每一条数据都需要先PREPARE,SQ_BIND,返回结果

MyBatis框架下,结合GBase8s JDBC驱动来操作GBase8s数据库,你可以按照以下步骤进行: 1. **添加依赖**: - 首先,你需要将GBase8s JDBC驱动(通常是一个.jar文件)添加到项目的类路径。如果你使用Maven,可以在pom.xml文件添加如下依赖: ```xml <dependency> <groupId>com.gbase</groupId> <artifactId>gbase8s-jdbc</artifactId> <version>版本号</version> </dependency> ``` 替换`版本号`为实际的驱动版本。 2. **配置数据源**: 在Spring Boot项目,可以创建一个DataSource实例,并配置GBase8s的URL、用户名和密码: ```java @Bean public DataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("com.gbase.jdbc.GBaseDriver"); dataSource.setUrl("jdbc:gbase://localhost:29700/your_database_name"); dataSource.setUsername("your_username"); dataSource.setPassword("your_password"); return dataSource; } ``` 3. **编写Mapper接口**: 创建一个MyBatis的Mapper接口,定义SQL映射方法,例如查询、插入、更新和删除操作: ```java // UserMapper.java public interface UserMapper { List<User> getAllUsers(); void addUser(User user); // 其他操作... } ``` 4. **XML映射文件**: 编写Mapper XML文件,描述如何将SQL语句与Mapper接口的方法对应起来: ```xml <!-- UserMapper.xml --> <mapper namespace="com.example.mapper.UserMapper"> <select id="getAllUsers" resultType="User"> SELECT * FROM users; </select> <insert id="addUser" parameterType="User"> INSERT INTO users (name, email) VALUES (${name}, ${email}); </insert> <!-- 添加其他SQL映射 --> </mapper> ``` 5. **注入Mapper**: 在需要使用的地方,通过SqlSession获取Mapper并进行数据库操作: ```java @Autowired private UserMapper userMapper; public void main() { SqlSession session = sqlSessionFactory.openSession(); try { List<User> users = userMapper.getAllUsers(); // 查询所有用户 userMapper.addUser(newUser); // 插入新用户 } finally { session.close(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值