Enterprise Java

Inserting BLOB Using Spring JdbcTemplate Example

1. Introduction

BLOB (Binary Large Object) is a large object data type in the database system. BLOB could store documents, images, audio, or video files. For smaller BLOBs, setting a byte array directly in memory is ok. For large BLOBs, streaming is more memory efficient. In this example, I will demonstrate how to use JdbcTemplate to insert and update a BLOB field in a PostgreSQL database.

2. Setup

In this step, I will create a Spring Boot (4.0.1) Java (21) project via Spring Initializer with PostgreSQL, Lombok, and JPA dependencies.

2.1 Build.gradle

Here is the generated build.gradle file.

build.gradle

plugins {
	id 'java'
	id 'org.springframework.boot' version '4.0.1'
	id 'io.spring.dependency-management' version '1.1.7'
}

group = 'org.jcg.zheng.demo'
version = '0.0.1-SNAPSHOT'
description = 'Demo project for BLOB'

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(21)
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
  	compileOnly 'org.projectlombok:lombok'
  	runtimeOnly 'org.postgresql:postgresql'
  	annotationProcessor 'org.projectlombok:lombok'
 	testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test'
 	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
	useJUnitPlatform()
}

2.2 InsertBlobApplication

Here is the generated InsertBlobApplication.java file.

InsertBlobApplication.java

package org.jcg.zheng.demo.insert_blob;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class InsertBlobApplication {

	public static void main(String[] args) {
		SpringApplication.run(InsertBlobApplication.class, args);
	}

}

2.3 Application Properties

Here is the updated application.properties file.

application.properties

spring.application.name=insert-blob

# DataSource configuration
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres?currentSchema=marydb
spring.datasource.username=postgres
spring.datasource.password=
spring.datasource.driver-class-name=org.postgresql.Driver

logging.level.org.springframework.jdbc.core.JdbcTemplate=trace
logging.level.org.springframework.jdbc.core.StatementCreatorUtils=trace

  • Line 9-10: enable the logging to show the raw SQL statement and binding parameters.

2.4 Start the Spring Boot Application

In this step, I will start the generated spring boot application and capture the server log.

Server Log

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v4.0.1)

2026-01-16T20:32:26.077-06:00  INFO 2864 --- [insert-blob] [           main] o.j.z.d.i.InsertBlobApplication          : Starting InsertBlobApplication using Java 21.0.8 with PID 2864 (C:\MaryZheng\workspace\insert-blob-postgre\bin\main started by zzhen in C:\MaryZheng\workspace\insert-blob-postgre)
2026-01-16T20:32:26.081-06:00  INFO 2864 --- [insert-blob] [           main] o.j.z.d.i.InsertBlobApplication          : No active profile set, falling back to 1 default profile: "default"
2026-01-16T20:32:26.440-06:00  INFO 2864 --- [insert-blob] [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2026-01-16T20:32:26.456-06:00  INFO 2864 --- [insert-blob] [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 10 ms. Found 0 JPA repository interfaces.
2026-01-16T20:32:26.617-06:00  INFO 2864 --- [insert-blob] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2026-01-16T20:32:26.844-06:00  INFO 2864 --- [insert-blob] [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@64f16277
2026-01-16T20:32:26.846-06:00  INFO 2864 --- [insert-blob] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2026-01-16T20:32:26.942-06:00  INFO 2864 --- [insert-blob] [           main] org.hibernate.orm.jpa                    : HHH008540: Processing PersistenceUnitInfo [name: default]
2026-01-16T20:32:27.012-06:00  INFO 2864 --- [insert-blob] [           main] org.hibernate.orm.core                   : HHH000001: Hibernate ORM core version 7.2.0.Final
2026-01-16T20:32:27.535-06:00  INFO 2864 --- [insert-blob] [           main] o.s.o.j.p.SpringPersistenceUnitInfo      : No LoadTimeWeaver setup: ignoring JPA class transformer
2026-01-16T20:32:27.592-06:00  INFO 2864 --- [insert-blob] [           main] org.hibernate.orm.connections.pooling    : HHH10001005: Database info:
	Database JDBC URL [jdbc:postgresql://localhost:5432/postgres?currentSchema=marydb]
	Database driver: PostgreSQL JDBC Driver
	Database dialect: PostgreSQLDialect
	Database version: 18.0
	Default catalog/schema: postgres/marydb
	Autocommit mode: undefined/unknown
	Isolation level: READ_COMMITTED [default READ_COMMITTED]
	JDBC fetch size: none
	Pool: DataSourceConnectionProvider
	Minimum pool size: undefined/unknown
	Maximum pool size: undefined/unknown
2026-01-16T20:32:28.238-06:00  INFO 2864 --- [insert-blob] [           main] org.hibernate.orm.core                   : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
2026-01-16T20:32:28.246-06:00  INFO 2864 --- [insert-blob] [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2026-01-16T20:32:28.436-06:00  INFO 2864 --- [insert-blob] [           main] o.j.z.d.i.InsertBlobApplication          : Started InsertBlobApplication in 2.647 seconds (process running for 2.928)
2026-01-16T20:32:28.446-06:00  INFO 2864 --- [insert-blob] [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2026-01-16T20:32:28.449-06:00  INFO 2864 --- [insert-blob] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2026-01-16T20:32:28.452-06:00  INFO 2864 --- [insert-blob] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
  • Line 21: shows the Spring boot application using the PostgreSQL database as the configuration file specified.

3. PostgreSQL Database Table with a BLOB Column

In this step, I will create a table with a BLOB column in a PostgreSQL database:

spring jdbctemplate insert blob
Figure 1. Demo_BLOB_Table

Create Table SQL

 create table demo_blob_table (
        id integer not null,
        content_type varchar(255),
        blob_col bytea,
        primary key (id)
    );
  • Line 4: The PostgreSQL bytea data type is used to map to a BLOB object.
  • Note: use different storage systems when a bytea field exceeds 1 GB.

3.1 Create a Java Entity

In this example, I will create the BlobMeta.java that maps to a database table for non-BLOB fields.

BlobMeta.java

package org.jcg.zheng.demo.insert_blob.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Data;

@Entity
@Table(name="demo_blob_table")
@Data
public class BlobMeta {
	
	@Id
	private Integer id;
	private String contentType;

}
  • Line 9: the BlobMeta entity is mapped to table demo_blob_table without BLOB fields to reduce memory usage as JPA caches objects in memory.

4. Spring JdbcTemplate Insert BLOB

In this step, I will create an InsertBlobService.java that inserts or updates a BLOB column with the following methods:

  • insert_with_ByteArray: insert a BLOB as byte[] directly using Spring JDBC.
  • insert_with_bytes: insert a BLOB with the setBytes() method that sets the designated parameter to the given Java array of bytes when BLOB data is less than 1 MB.
  • insert_with_BinaryStream: insert a BLOB and use the setBinaryStream method to set the designated parameter to the given input stream. It’s good when BLOB data is greater than 1 MB and less than 1 GB.
  • insert_with_SQLVarbinary: insert a BLOB using Spring JDBC, explicitly treating the bytes array as SqlParameterValue(Types.VARBINARY) so the database stores it correctly.
  • readBlob_asObject: read a BLOB via the JdbcTemplate.queryForObject method. The return data is in memory. it’s ok for smaller BLOB objects.
  • readBlob_asStream: read a BLOB via the JdbcTemplate.queryForStream method. It streams into the InputStream and then writes to a file. It’s more memory efficient.
  • update_with_bytes: update a BLOC via the setBytes method.

InsertBlobService.java

package org.jcg.zheng.demo.insert_blob.service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.sql.PreparedStatement;
import java.sql.Types;
import java.util.stream.Stream;

import org.jcg.zheng.demo.insert_blob.entity.BlobMeta;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.SqlParameterValue;
import org.springframework.stereotype.Service;

import jakarta.transaction.Transactional;

@Service
@Transactional
public class InsertBlobService {

	private static final String SELECT_BLOB_SQL = "SELECT blob_col from demo_blob_table WHERE id=?";
	private static final String UPDATE_BLOB_SQL = "UPDATE demo_blob_table set blob_col=? WHERE id=?";
	private static final String INSERT_BLOB_SQL = "INSERT INTO demo_blob_table(id, content_type, blob_col) VALUES (?,?,?)";

	private final JdbcTemplate jdbcTemplate;

	public InsertBlobService(JdbcTemplate jdbcTemplate) {
		super();
		this.jdbcTemplate = jdbcTemplate;
	}

	public void insert_with_ByteArray(BlobMeta blobMeta, byte[] data) {
		jdbcTemplate.update(INSERT_BLOB_SQL, blobMeta.getId(), blobMeta.getContentType(), data);
	}

	public void insert_with_SQLVarbinary(BlobMeta blobMeta, byte[] data) {
		jdbcTemplate.update(INSERT_BLOB_SQL, blobMeta.getId(), blobMeta.getContentType(),
				new SqlParameterValue(Types.VARBINARY, data));
	}

	public void insert_with_BinaryStream(BlobMeta blobMeta, byte[] data) {
		jdbcTemplate.update(con -> {
			PreparedStatement ps = con.prepareStatement(INSERT_BLOB_SQL);
			ps.setInt(1, blobMeta.getId());
			ps.setString(2, blobMeta.getContentType());
			ps.setBinaryStream(3, new ByteArrayInputStream(data));
			return ps;
		});
	}

	public void insert_with_bytes(BlobMeta blobMeta, byte[] data) {
		jdbcTemplate.update(con -> {
			PreparedStatement ps = con.prepareStatement(INSERT_BLOB_SQL);
			ps.setInt(1, blobMeta.getId());
			ps.setString(2, blobMeta.getContentType());
			ps.setBytes(3, data);
			return ps;
		});
	}

	public byte[] readBlob_asObject(int id) {
		return jdbcTemplate.queryForObject(SELECT_BLOB_SQL, byte[].class, id);
	}

	public void readBlob_asStream(int id) {
		Path target = Paths.get("output.bin");
		try (Stream<InputStream> stream = jdbcTemplate.queryForStream(SELECT_BLOB_SQL,
				(rs, rowNum) -> rs.getBinaryStream("blob_col"), id)) {
			stream.findFirst().ifPresent(inputStream -> {

				try (InputStream in = inputStream) {
					Files.copy(in, target, StandardCopyOption.REPLACE_EXISTING);
				} catch (IOException e) {
					e.printStackTrace();
				}
			});

		}

	}

	public void update_with_bytes(int id, byte[] data) {
		jdbcTemplate.update(UPDATE_BLOB_SQL, ps -> {
			ps.setBytes(1, data);
			ps.setInt(2, id);
		});
	}

}
  • Line 25-27: the raw SQL statements to insert, update, and select BLOB data.
  • Line 37: map byte[] directly in the insert statement.
  • Line 42: use SqlParameterValue(Types.VARBINARY) to map to byte[] to ensure correct JDBC type and avoid JDBC driver-specific issues. It prevents binary data being treated as VARCHAR and works across databases ( MySQL, SQL Server, Oracle, PostgreSQL).
  • Line 50: setBinaryStream maps to InputStream for streaming into the database.
  • Line 60: use setBytes maps to byte[].
  • Line 66: queryForObject maps to byte[] in memory.
  • Line 71: queryForStream maps to InputStream.
  • Line 75: try-with-resources clause closes InputStream explicitly.
  • Line 76: Files.copy writes the BLOB into a file.
  • Line 88: setBytes is used in an update statement.

5. Test InsertBlobService

In this step, I will create a InsertBlobServiceTest.java that tests the methods to insert, update, and select a BLOB column.

InsertBlobServiceTest.java

package org.jcg.zheng.demo.insert_blob.service;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.jcg.zheng.demo.insert_blob.entity.BlobMeta;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class InsertBlobServiceTest {

	private static final String BLOB_STRING = "this is blob";
	private static final String BLOB_STRING_2 = "this is blob 2";
	@Autowired
	private InsertBlobService testClass;

	@Test
	void test_insert_with_BinaryStream() {
		int test_id = 2;

		testClass.insert_with_BinaryStream(testBlobMeta(test_id), BLOB_STRING.getBytes());

		byte[] ret = testClass.readBlob_asObject(test_id);

		assertEquals(BLOB_STRING, new String(ret));

	}

	@Test
	void test_insert_with_ByteArray() {
		int test_id = 1;

		testClass.insert_with_ByteArray(testBlobMeta(test_id), BLOB_STRING.getBytes());

		byte[] ret = testClass.readBlob_asObject(test_id);

		assertEquals(BLOB_STRING, new String(ret));
	
		testClass.readBlob_asStream(1);

	}

	@Test
	void test_insert_with_bytes() {
		int test_id = 3;

		testClass.insert_with_bytes(testBlobMeta(test_id), BLOB_STRING.getBytes());

		byte[] ret = testClass.readBlob_asObject(test_id);

		assertEquals(BLOB_STRING, new String(ret));

	}

	@Test
	void test_insert_with_SQLVarbinary() {
		int test_id = 4;

		testClass.insert_with_SQLVarbinary(testBlobMeta(test_id), BLOB_STRING.getBytes());

		byte[] ret = testClass.readBlob_asObject(test_id);

		assertEquals(BLOB_STRING, new String(ret));

	}

	
	@Test
	void test_update_with_bytes() {
		int test_id = 1;
		byte[] ret = testClass.readBlob_asObject(test_id);
		if (ret == null) {
			testClass.insert_with_ByteArray(testBlobMeta(test_id), BLOB_STRING.getBytes());
		}

		testClass.update_with_bytes(1, BLOB_STRING_2.getBytes());

		assertEquals(BLOB_STRING_2, new String(testClass.readBlob_asObject(1)));

	}

	private BlobMeta testBlobMeta(int id) {
		BlobMeta blobMeta = new BlobMeta();
		blobMeta.setId(id);
		blobMeta.setContentType("txt");
		return blobMeta;
	}
}

Run tests and capture output.

spring jdbctemplate insert blob
Figure 2. Unit Tests

The console log shows the actual SQL statements and the binding parameters.

InsertBlobServiceTest Console Log

20:36:30.695 [main] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils -- Could not detect default configuration classes for test class [org.jcg.zheng.demo.insert_blob.service.InsertBlobServiceTest]: InsertBlobServiceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
20:36:30.773 [main] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper -- Found @SpringBootConfiguration org.jcg.zheng.demo.insert_blob.InsertBlobApplication for test class org.jcg.zheng.demo.insert_blob.service.InsertBlobServiceTest

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::                (v4.0.1)

2026-01-16T20:36:31.076-06:00  INFO 26912 --- [insert-blob] [           main] o.j.z.d.i.service.InsertBlobServiceTest  : Starting InsertBlobServiceTest using Java 21.0.8 with PID 26912 (started by zzhen in C:\MaryZheng\workspace\insert-blob-postgre)
2026-01-16T20:36:31.076-06:00  INFO 26912 --- [insert-blob] [           main] o.j.z.d.i.service.InsertBlobServiceTest  : No active profile set, falling back to 1 default profile: "default"
2026-01-16T20:36:31.322-06:00  INFO 26912 --- [insert-blob] [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode.
2026-01-16T20:36:31.339-06:00  INFO 26912 --- [insert-blob] [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 8 ms. Found 0 JPA repository interfaces.
2026-01-16T20:36:31.520-06:00  INFO 26912 --- [insert-blob] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2026-01-16T20:36:31.696-06:00  INFO 26912 --- [insert-blob] [           main] com.zaxxer.hikari.pool.HikariPool        : HikariPool-1 - Added connection org.postgresql.jdbc.PgConnection@31f295b6
2026-01-16T20:36:31.697-06:00  INFO 26912 --- [insert-blob] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed.
2026-01-16T20:36:31.778-06:00  INFO 26912 --- [insert-blob] [           main] org.hibernate.orm.jpa                    : HHH008540: Processing PersistenceUnitInfo [name: default]
2026-01-16T20:36:31.842-06:00  INFO 26912 --- [insert-blob] [           main] org.hibernate.orm.core                   : HHH000001: Hibernate ORM core version 7.2.0.Final
2026-01-16T20:36:32.239-06:00  INFO 26912 --- [insert-blob] [           main] o.s.o.j.p.SpringPersistenceUnitInfo      : No LoadTimeWeaver setup: ignoring JPA class transformer
2026-01-16T20:36:32.327-06:00  INFO 26912 --- [insert-blob] [           main] org.hibernate.orm.connections.pooling    : HHH10001005: Database info:
	Database JDBC URL [jdbc:postgresql://localhost:5432/postgres?currentSchema=marydb]
	Database driver: PostgreSQL JDBC Driver
	Database dialect: PostgreSQLDialect
	Database version: 18.0
	Default catalog/schema: postgres/marydb
	Autocommit mode: undefined/unknown
	Isolation level: READ_COMMITTED [default READ_COMMITTED]
	JDBC fetch size: none
	Pool: DataSourceConnectionProvider
	Minimum pool size: undefined/unknown
	Maximum pool size: undefined/unknown
2026-01-16T20:36:32.899-06:00  INFO 26912 --- [insert-blob] [           main] org.hibernate.orm.core                   : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
2026-01-16T20:36:32.905-06:00  INFO 26912 --- [insert-blob] [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2026-01-16T20:36:33.074-06:00  INFO 26912 --- [insert-blob] [           main] o.j.z.d.i.service.InsertBlobServiceTest  : Started InsertBlobServiceTest in 2.187 seconds (process running for 3.087)
Mockito is currently self-attaching to enable the inline-mock-maker. This will no longer work in future releases of the JDK. Please add Mockito as an agent to your build as described in Mockito's documentation: https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#0.3
WARNING: A Java agent has been loaded dynamically (C:\Users\zzhen\.gradle\caches\modules-2\files-2.1\net.bytebuddy\byte-buddy-agent\1.17.8\f09415827a71be7ed621c7bd02550678f28bc81c\byte-buddy-agent-1.17.8.jar)
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
WARNING: Dynamic loading of agents will be disallowed by default in a future release
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended
2026-01-16T20:36:33.443-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2026-01-16T20:36:33.443-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT INTO demo_blob_table(id, content_type, blob_col) VALUES (?,?,?)]
2026-01-16T20:36:33.450-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [4], value class [java.lang.Integer], SQL type unknown
2026-01-16T20:36:33.450-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 2, parameter value [txt], value class [java.lang.String], SQL type unknown
2026-01-16T20:36:33.451-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 3, parameter value [[B@2604940], value class [[B], SQL type -3
2026-01-16T20:36:33.453-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : SQL update affected 1 rows
2026-01-16T20:36:33.461-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2026-01-16T20:36:33.463-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT blob_col from demo_blob_table WHERE id=?]
2026-01-16T20:36:33.463-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [4], value class [java.lang.Integer], SQL type unknown
2026-01-16T20:36:33.473-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2026-01-16T20:36:33.473-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement
2026-01-16T20:36:33.473-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : SQL update affected 1 rows
2026-01-16T20:36:33.477-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2026-01-16T20:36:33.477-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT blob_col from demo_blob_table WHERE id=?]
2026-01-16T20:36:33.477-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [3], value class [java.lang.Integer], SQL type unknown
2026-01-16T20:36:33.480-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2026-01-16T20:36:33.480-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT INTO demo_blob_table(id, content_type, blob_col) VALUES (?,?,?)]
2026-01-16T20:36:33.480-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [1], value class [java.lang.Integer], SQL type unknown
2026-01-16T20:36:33.480-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 2, parameter value [txt], value class [java.lang.String], SQL type unknown
2026-01-16T20:36:33.480-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 3, parameter value [[B@c8ed958], value class [[B], SQL type unknown
2026-01-16T20:36:33.481-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : SQL update affected 1 rows
2026-01-16T20:36:33.482-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2026-01-16T20:36:33.482-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT blob_col from demo_blob_table WHERE id=?]
2026-01-16T20:36:33.482-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [1], value class [java.lang.Integer], SQL type unknown
2026-01-16T20:36:33.484-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT blob_col from demo_blob_table WHERE id=?]
2026-01-16T20:36:33.484-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [1], value class [java.lang.Integer], SQL type unknown
2026-01-16T20:36:33.489-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2026-01-16T20:36:33.489-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT blob_col from demo_blob_table WHERE id=?]
2026-01-16T20:36:33.489-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [1], value class [java.lang.Integer], SQL type unknown
2026-01-16T20:36:33.490-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2026-01-16T20:36:33.490-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [UPDATE demo_blob_table set blob_col=? WHERE id=?]
2026-01-16T20:36:33.491-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : SQL update affected 1 rows
2026-01-16T20:36:33.492-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2026-01-16T20:36:33.492-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT blob_col from demo_blob_table WHERE id=?]
2026-01-16T20:36:33.492-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [1], value class [java.lang.Integer], SQL type unknown
2026-01-16T20:36:33.495-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL update
2026-01-16T20:36:33.495-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement
2026-01-16T20:36:33.496-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : SQL update affected 1 rows
2026-01-16T20:36:33.496-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query
2026-01-16T20:36:33.496-06:00 DEBUG 26912 --- [insert-blob] [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT blob_col from demo_blob_table WHERE id=?]
2026-01-16T20:36:33.497-06:00 TRACE 26912 --- [insert-blob] [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [2], value class [java.lang.Integer], SQL type unknown
2026-01-16T20:36:33.505-06:00  INFO 26912 --- [insert-blob] [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2026-01-16T20:36:33.507-06:00  INFO 26912 --- [insert-blob] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2026-01-16T20:36:33.512-06:00  INFO 26912 --- [insert-blob] [ionShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

6. Conclusion

In this example, I demonstrated several ways to insert, update, and select a BLOB field in the PostgreSQL database.

7. Download

This was an example of inserting BLOB fields via Spring JdbcTemplate.

Download
You can download the full source code of this example here: Inserting BLOB Using Spring JdbcTemplate Example

Mary Zheng

Mary graduated from the Mechanical Engineering department at ShangHai JiaoTong University. She also holds a Master degree in Computer Science from Webster University. During her studies she has been involved with a large number of projects ranging from programming and software engineering. She worked as a lead Software Engineer where she led and worked with others to design, implement, and monitor the software solution.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button