Databases 13 min read

Efficient Insertion of 300,000 Records Using MyBatis and JDBC

The article shows how to efficiently load 300,000 MySQL rows in Java by comparing MyBatis and plain-JDBC batch inserts, demonstrating that batching 1,000‑5,000 records per transaction with proper transaction control, connection pooling, and MySQL tuning reduces insertion time from hours to seconds.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Efficient Insertion of 300,000 Records Using MyBatis and JDBC

This article demonstrates how to insert a large volume of data (300,000 rows) into a MySQL table using both MyBatis and plain JDBC, compares different insertion strategies, and provides performance‑tuning tips.

User entity definition (Lombok @Data used)

/**
 *
用户实体
*
 * @Author zjq
 * @Date 2021/8/3
 */
@Data
public class User {
    private int id;
    private String username;
    private int age;
}

Mapper interface

public interface UserMapper {
    /**
     * 批量插入用户
     * @param userList
     */
    void batchInsertUser(@Param("list") List
userList);
}

Mapper XML for batch insert

insert into t_user(username,age) values
(#{item.username}, #{item.age})

MyBatis test method (single‑batch, 1000 rows per commit)

@Test
public void testBatchInsertUser() throws IOException {
    InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    SqlSession session = sqlSessionFactory.openSession();
    System.out.println("===== 开始插入数据 =====");
    long startTime = System.currentTimeMillis();
    try {
        List
userList = new ArrayList<>();
        for (int i = 1; i <= 300000; i++) {
            User user = new User();
            user.setId(i);
            user.setUsername("共饮一杯无 " + i);
            user.setAge((int) (Math.random() * 100));
            userList.add(user);
            if (i % 1000 == 0) {
                session.insert("batchInsertUser", userList);
                session.commit();
                userList.clear();
                Thread.sleep(10 * 1000); // optional wait
            }
        }
        if (!userList.isEmpty()) {
            session.insert("batchInsertUser", userList);
            session.commit();
        }
        long spendTime = System.currentTimeMillis() - startTime;
        System.out.println("成功插入 30 万条数据,耗时:" + spendTime + "毫秒");
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        session.close();
    }
}

JDBC batch‑insert test method

@Test
public void testJDBCBatchInsertUser() throws IOException {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    String databaseURL = "jdbc:mysql://localhost:3306/test";
    String user = "root";
    String password = "root";
    try {
        connection = DriverManager.getConnection(databaseURL, user, password);
        connection.setAutoCommit(false);
        System.out.println("===== 开始插入数据 =====");
        long startTime = System.currentTimeMillis();
        String sqlInsert = "INSERT INTO t_user (username, age) VALUES (?, ?)";
        preparedStatement = connection.prepareStatement(sqlInsert);
        Random random = new Random();
        for (int i = 1; i <= 300000; i++) {
            preparedStatement.setString(1, "共饮一杯无 " + i);
            preparedStatement.setInt(2, random.nextInt(100));
            preparedStatement.addBatch();
            if (i % 1000 == 0) {
                preparedStatement.executeBatch();
                connection.commit();
                System.out.println("成功插入第 " + i + " 条数据");
            }
        }
        preparedStatement.executeBatch();
        connection.commit();
        long spendTime = System.currentTimeMillis() - startTime;
        System.out.println("成功插入 30 万条数据,耗时:" + spendTime + "毫秒");
    } catch (SQLException e) {
        System.out.println("Error: " + e.getMessage());
    } finally {
        if (preparedStatement != null) {
            try { preparedStatement.close(); } catch (SQLException ignored) {}
        }
        if (connection != null) {
            try { connection.close(); } catch (SQLException ignored) {}
        }
    }
}

Performance observations:

Direct "one‑shot" batch of 300k rows exceeds MySQL's max_allowed_packet and fails.

Inserting row‑by‑row via MyBatis takes several hours (≈4 h) and saturates disk I/O.

Batching 1000 rows with a short pause reduces memory pressure; total time drops to ~5 min.

Increasing batch size to 5000 rows and removing the pause can finish in ~13 s on a fast machine.

Optimization recommendations:

Use batch size between 1000‑5000 rows to balance memory usage and network overhead.

Temporarily drop indexes before bulk load, rebuild them afterward.

Configure a connection pool (e.g., HikariCP) to avoid repeated connection creation.

Adjust MySQL parameters such as innodb_buffer_pool_size and max_allowed_packet as needed.

Consider using prepared statements with addBatch() and manual transaction control.

In summary, efficient large‑scale data insertion in Java requires proper batching, transaction management, and database tuning.

JavaperformancedatabaseMyBatisJDBCbatch insert
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.