{"id":32868508,"url":"https://github.com/spring-jdbc-crud/simplejdbcmapper","last_synced_at":"2026-04-18T03:01:52.449Z","repository":{"id":317883398,"uuid":"1068640331","full_name":"spring-jdbc-crud/simplejdbcmapper","owner":"spring-jdbc-crud","description":"A library that simplifies Spring JdbcTemplate/JdbcClient CRUD operations by making them less verbose.","archived":false,"fork":false,"pushed_at":"2026-04-12T23:25:00.000Z","size":1708,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-13T01:18:19.976Z","etag":null,"topics":["crud","jdbcclient","jdbctemplate","spring"],"latest_commit_sha":null,"homepage":"https://spring-jdbc-crud.github.io/simplejdbcmapper/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spring-jdbc-crud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-02T17:27:33.000Z","updated_at":"2026-04-10T11:18:25.000Z","dependencies_parsed_at":null,"dependency_job_id":"089f4ac9-2523-44ee-b2b4-4049aac43c19","html_url":"https://github.com/spring-jdbc-crud/simplejdbcmapper","commit_stats":null,"previous_names":["spring-jdbc-crud/simplejdbcmapper"],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/spring-jdbc-crud/simplejdbcmapper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spring-jdbc-crud%2Fsimplejdbcmapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spring-jdbc-crud%2Fsimplejdbcmapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spring-jdbc-crud%2Fsimplejdbcmapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spring-jdbc-crud%2Fsimplejdbcmapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spring-jdbc-crud","download_url":"https://codeload.github.com/spring-jdbc-crud/simplejdbcmapper/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spring-jdbc-crud%2Fsimplejdbcmapper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31954736,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crud","jdbcclient","jdbctemplate","spring"],"created_at":"2025-11-09T08:01:24.054Z","updated_at":"2026-04-18T03:01:52.442Z","avatar_url":"https://github.com/spring-jdbc-crud.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SimpleJdbcMapper #\n[![CI SimpleJdbcMapper](https://github.com/spring-jdbc-crud/simplejdbcmapper/actions/workflows/ci.yml/badge.svg)](https://github.com/spring-jdbc-crud/simplejdbcmapper/actions/workflows/ci.yml)  [![coverage](https://spring-jdbc-crud.github.io/simplejdbcmapper/jacoco/jacoco.svg)](https://spring-jdbc-crud.github.io/simplejdbcmapper/jacoco/index.html)  [![maven-central](https://img.shields.io/maven-central/v/io.github.spring-jdbc-crud/simplejdbcmapper)](https://central.sonatype.com/artifact/io.github.spring-jdbc-crud/simplejdbcmapper)  [![License](https://img.shields.io/:license-apache-brightgreen.svg)](https://central.sonatype.com/artifact/io.github.spring-jdbc-crud/simplejdbcmapper)\n\nA library that simplifies Spring JdbcTemplate/JdbcClient CRUD operations by making them less verbose. Use it as needed and keep using JdbcTemplate/JdbcClient for other functionality.\n\nJust by annotating the models that you would use with JdbcTemplate/JdbcClient, you get single-line CRUD. Also, you will be able to use Spring row mappers like BeanPropertyRowMapper and SimplePropertyRowMapper etc for certain custom queries, avoiding writing custom row mappers.\n\n[Javadoc](https://spring-jdbc-crud.github.io/simplejdbcmapper/javadoc/index.html) | [Demo Application](https://github.com/spring-jdbc-crud/spring-crud-with-simplejdbcmapper) | [Dzone Article](https://dzone.com/articles/using-simplejdbcmapper-with-spring)\n\n## Table of contents\n[Features](#features)  \n[Maven coordinates](#maven-coordinates)   \n[Example code](#example-code)  \n[JDK and Spring version requirements](#jdk-and-spring-version-requirements)  \n[Spring bean configuration for SimpleJdbcMapper](#spring-bean-configuration-for-simplejdbcmapper)  \n[Annotations](#annotations)  \n[BLOB CLOB mapping](#blob-clob-mapping)  \n[Enum mapping](#enum-mapping)  \n[Configuration for auto assigning @CreatedBy, @UpdateBy, @CreatedOn, @UpdatedOn](#configuration-for-auto-assigning-createdby-updateby-createdon-updatedon)  \n[Accessing JdbcClient JdbcTemplate](#accessing-jdbcclient-jdbctemplate)  \n[Logging](#logging)  \n[Limitations](#limitations)  \n[Upgrading to 2.x from 1.x](#upgrading-to-2x-from-1x)  \n[Troubleshooting](#troubleshooting)  \n[Bug Report](https://github.com/spring-jdbc-crud/simplejdbcmapper/issues) \n\n## Features\n1. One liners for CRUD\n2. Simple configuration similar to Jdbctemplate/JdbClient configuration.\n3. Helper methods to construct SQL for the mapped objects that can be used with Spring row mappers like BeanPropertyRowMapper, SimplePropertyRowMapper, which avoids writing custom row mappers.\n4. Auto assign properties\n    * auto assign audited  by (created by, updated by) by providing a Supplier\n    * auto assign audited on (created on, updated on) by providing a Supplier\n    * optimistic locking feature for updates using versioning.\n5. Transaction management is the same as in Spring applications since the library is using JdbcTemplate behind the scenes.\n5. To log the SQL statements use the same SQL logging configurations as Spring. See the logging section further below.\n7. Tests are run against PostgreSQL, MySQL, Oracle, SQLServer. Should work with other databases.\n[![CI SimpleJdbcMapper](https://github.com/spring-jdbc-crud/simplejdbcmapper/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/spring-jdbc-crud/simplejdbcmapper/actions/workflows/ci.yml)\n8. Only dependency is Spring JDBC libraries. No other external dependencies.\n\n## Maven coordinates\n\n ``` \n  \u003cdependency\u003e\n    \u003cgroupId\u003eio.github.spring-jdbc-crud\u003c/groupId\u003e\n    \u003cartifactId\u003esimplejdbcmapper\u003c/artifactId\u003e\n    \u003cversion\u003e2.1.0\u003c/version\u003e\n \u003c/dependency\u003e\n ```\n \n\n## Example code\n  ```java \n //@Table annotation is required\n @Table(name=\"product\")\n public class Product {\n     /*\n      The @Id annotation is required. It can be of any type.\n      @Id(type=IdType.AUTO_GENERATED) - Use for ids which are auto generated by the database. Id value will \n                                        be assigned to the object on insert.\n      @Id - The id value will have to be manually set before invoking insert().                                                            \n     */\n     @Id(type=IdType.AUTO_GENERATED)\n     private Integer id; \n             \n     // The 'name' property will map to 'product_name' column in database table.\n     @Column(name=\"product_name\")            \n     private String name;\n     \n     // will map to column 'sku'\n     @Column\n     private string sku;                 \n     \n     // will map to column 'available_date' by default using camel case to underscore case naming convention\n     @Column\n     private LocalDateTime availableDate;    \n     \n     // will map to 'price' column by default\n     @Column\n     private Double price;                   \n     \n     // No annotations for this property so excluded from inserts/updates/queries etc\n     private String someNonDatabaseProperty; \n \n     ...\n }\n\n ...\n @Autowired\n private SimpleJdbcMapper sjm;\n...\n\n Product product = new Product();\n product.setName(\"some product name\");\n product.setSku(\"sku1\");\n product.setPrice(10.25);\n product.setAvailableDate(LocalDateTime.now());\n \n // because id type is AUTO_GENERATED its value will be assigned on insert.\n sjm.insert(product); \n\n // find by id\n product = sjm.findById(Product.class, product.getId());\n \n // update product\n product.setPrice(11.50);\n sjm.update(product);\n \n // updateSpecificProperties() updates only the specified properties passed as arguments.\n // Will issue an SQL update only for price.\n product.setPrice(12.50);\n sjm.updateSpecificProperties(product, \"price\");\n \n // find all\n List\u003cProduct\u003e products = sjm.findAll(Product.class);\n \n // find all with sort (ORDER BY clause)\n  List\u003cProduct\u003e products = sjm.findAll(Product.class, new SortBy(\"availabeDate\"), new SortBy(\"price\", \"DESC\"));\n \n // delete by object\n sjm.delete(product);\n \n // delete by id\n sjm.deleteById(Product.class, 5);\n \n /*\n  For custom queries use getBeanFriendlySqlColumns() to get the columns sql. It creates the appropriate column aliases \n  when the column name does not match the corresponding underscore case property name. This allows the usage of \n  Spring row mappers like BeanPropertyRowMapper, SimplePropertyRowMapper etc instead of writing custom row mappers. \n  Note in this case the 'name' property is mapped to the 'product_name' column.\n */\n String sql = \"SELECT \" + sjm.getBeanFriendlySqlColumns(Product.class) +  \" FROM product WHERE product_name = ?\";\n \n // Using Spring's JdbcClient api for the above sql. JdbcClient is using SimplePropertyRowMapper internally here.\n List\u003cProduct\u003e products = sjm.getJdbcClient().sql(sql).param(\"someProductName\").query(Product.class).list();\n \n // Using Spring's JdbcTemplate api for the above sql\n List\u003cProduct\u003e products = sjm.getJdbcTemplate().query(sql, BeanPropertyRowMapper.newInstance(Product.class), \"someProductName\");\n \n // find by a property value\n List\u003cProduct\u003e products = sjm.findByPropertyValue(Product.class, \"sku\", \"some sku#\");\n \n // find by multiple property values\n String[] skus = { \"sku1\", \"sku2\"};\n List\u003cProduct\u003e products = sjm.findByPropertyValues(Product.class, \"sku\", Array.asList(skus));\n \n // Accessing the underlying JdbcClient, JdbcTemplate and NamedParameterJdbcTemplate. \n JdbcClient jdbcClient = sjm.getJdbcClient();\n JdbcTemplate jdbcTemplate = sjm.getJdbcTemplate();\n NamedParameterJdbcTemplate namedParameterJdbcTemplate = sjm.getNamedParameterJdbcTemplate();\n \n // The demo application (link provided at top) is easy to install and run where you can see example code in action.\n \n // See logging section for details to view the SQL\n \n // See troubleshooting section if you have issues.\n \n // Thats all folks. Happy coding!!!\n ```\n## JDK and Spring version requirements\n\nJDK **21+**\n\nSpringBoot **3.2.3+** or Spring framework **6.1.4+**\n \n## Spring bean configuration for SimpleJdbcMapper\n\nSimpleJdbcMapper should always be prepared in a Spring application context and given to services as a bean reference. It maintains state for example it caches insert/update SQL etc.\n\n**Note: An instance of SimpleJdbcMapper is thread safe once configured.**\n\nExamples for different databases below. Depending on the versions of springboot/database/driver, there could be some differences to the properties. The properties are same as datasource properties used to configure Spring JdbcClient/JdbcTemplate.\n\n**PostgreSQL**\n\n``` \n# application.properties\nspring.datasource.jdbc-url=jdbc:postgresql://HOST:PORT/SCHEMA_NAME\nspring.datasource.username=username\nspring.datasource.password=password\nspring.datasource.driver-class-name=org.postgresql.Driver\n...\n\n  // DataSource properties are read from application.properties.\n  @Bean\n  @ConfigurationProperties(prefix = \"spring.datasource\")\n  public DataSource sqlDataSource() {\n    return DataSourceBuilder.create().build();\n  }\n\n @Bean\n  public SimpleJdbcMapper simpleJdbcMapper(DataSource dataSource) {\n    return new SimpleJdbcMapper(dataSource, SCHEMA_NAME);\n  }\n  \n```\n \n**MySQL**\n\n``` \n# application.properties\nspring.datasource.jdbc-url=jdbc:mysql://HOST:PORT/DATABASE_NAME\nspring.datasource.username=username\nspring.datasource.password=password\nspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver\n...\n\n  // DataSource properties are read from application.properties.\n  @Bean\n  @ConfigurationProperties(prefix = \"spring.datasource\")\n  public DataSource sqlDataSource() {\n    return DataSourceBuilder.create().build();\n  }\n\n @Bean\n  public SimpleJdbcMapper simpleJdbcMapper(DataSource dataSource) {\n    return new SimpleJdbcMapper(dataSource, null, DATABASE_NAME); // For mysql, database is synonymous with catalog\n  }\n\n```\n\n**Oracle**\n\n``` \n# application.properties\nspring.datasource.jdbc-url=jdbc:oracle:thin:@HOST:PORT/SERVICE_NAME\nspring.datasource.username=username\nspring.datasource.password=password\nspring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver\n...\n\n  // DataSource properties are read from application.properties.\n  @Bean\n  @ConfigurationProperties(prefix = \"spring.datasource\")\n  public DataSource sqlDataSource() {\n    return DataSourceBuilder.create().build();\n  }\n  \n @Bean\n  public SimpleJdbcMapper simpleJdbcMapper(DataSource dataSource) {   \n   return new SimpleJdbcMapper(dataSource, SCHEMA_NAME);\n  }\n\n```\n\n**SQLServer**\n\n``` \n# application.properties\nspring.datasource.jdbc-url=jdbc:sqlserver://HOST:PORT;databaseName=CATALOG_NAME;encrypt=true;trustServerCertificate=true;\nspring.datasource.username=username\nspring.datasource.password=password\nspring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver\n...\n\n  // DataSource properties are read from application.properties.\n  @Bean\n  @ConfigurationProperties(prefix = \"spring.datasource\")\n  public DataSource sqlDataSource() {\n    return DataSourceBuilder.create().build();\n  }\n  \n @Bean\n  public SimpleJdbcMapper simpleJdbcMapper(DataSource dataSource) {\n    return new SimpleJdbcMapper(dataSource, SCHEMA_NAME);\n  }\n  \n```\n\n## Annotations\n\n**@Table**\n\nRequired class level annotation. The table or view should exist in database. The schema/catalog attributes set with @Table will override corresponding values on the SimpleJdbcMapper() constructor (if any). **Note that table names with spaces are not supported.**\n\nMultiple objects can be mapped to the same table. For example if you have a table with large number of columns you could have 2 objects mapped to it. One with a few commonly used columns and another with all the columns.\n\n```java \n\n@Table(name=\"product\")\nclass Product {\n  ...\n}\n\n@Table(name=\"product\", schema=\"someSchemaName\") \nclass Product {\n  ...\n}\n\n@Table(name=\"product\", catalog=\"someCatalogName\")  // for mysql, database name is synonymous with catalog name \nclass Product {\n  ...\n}\n\n@Table(name=\"product\", catalog=\"someCatalogName\", schema=\"someSchemaName\")\nclass Product {\n  ...\n}\n\n```\n\n**@Id**\n\nThe id property can be of any java type. @Id can only be mapped to a single database column. **Multi-column ids  are not supported.**\n\nThere are 2 forms of usage for this.\n\n* **auto generated id usage**\n\n```java \n\n@Table(name=\"product\")\nclass Product {\n @Id(type=IdType.AUTO_GENERATED)\n private Integer productId;\n  ...\n}\n\n```\nAfter a successful insert() operation the productId property will be populated with the generated id.\n\n* **NON auto generated id usage**\n\n```java \n\n@Table(name=\"customer\")\nclass Customer {\n @Id\n private Integer id;\n  ...\n}\n```\n\nIn this case you will have to manually set the id value before invoking insert()  \n\n**@Column**\n\nProperties that need be persisted to the database will need @Column annotation unless the property is already annotated with one of the other annotations (@Id, @Version, @CreatedOn @CreatedBy @UpdatedOn @UpdatedBy). @Column can be used along with the other annotations to map a property to a non-default column name. The default column name is camel case property name converted to underscore case name (e.g., property 'lastName' maps to column 'last_name' by default).\n\n***@Column*** \nThis will map the property to a column using the default naming convention of camel case to underscore case. For example property 'lastName' will map to column 'last_name' by default.  \n\n***@Column(name=\"somecolumnname\")*** \nThis will map the property to the column specified by the 'name' attribute.  **Note that column names with spaces are not supported.**  \n\n***@Column(sqlType = somesqltype)***  \nSimpleJdbcMapper tries to infer the correct SQL type from the Java types but some times it cannot. In these cases explicitly declaring the SQL type is a best practice to ensure correctness, improve performance, and correctly handle NULL values. \n \nTo identify which properties in the mappings the SQL type is unknown do the following:\n   - Turn on sql logging. (See logging section)\n   - Issue an insert/update for the entity.\n   - Check for 'SQL type unknown' in the logs. Below is example of the logs. Line 1 has the SQL type while line 2 the SQL type is unknown:  \n   \n```\n   Setting SQL statement parameter value: column index 6, parameter value [true], value class [java.lang.Boolean], SQL type 16  \n   Setting SQL statement parameter value: column index 7, parameter value [[B@56d742ad], value class [[B], SQL type unknown\n```\n   - For your specific database and database column type find the corresponding SQL type and assign it using @Column(sqlType = somesqltype).\n\n**@Version**\n\nThis annotation is used for optimistic locking. It has to be of type Integer.\nWill be set to 1 when record is created and will be incremented on updates. On updates if the version is stale an OptimisticLockingException will be thrown.  @Column annotation can be used with the property to map to a non-default column name.\n\n**@CreatedOn**\n\nIf a Supplier is configured using simpleJdbcMapper.setRecordAuditedOnSupplier(), it will be used to to set the value for the @CreatedOn property. The type of the Supplier should match the type of the property. @Column annotation can also be used with the property to map to a non-default  column name.\n\n**@UpdatedOn**\n\nIf a Supplier is configured using simpleJdbcMapper.setRecordAuditedOnSupplier(), it will be used to to set the value for the @UpdatedOn property. The type of the Supplier should match the type of the property. @Column annotation can also be used with the property to map to a non-default  column name.\n\n**@CreatedBy**\n\nIf a Supplier is configured using simpleJdbcMapper.setRecordAuditedBySupplier(), it will be used to to set the value for the @CreatedBy property. The type of the Supplier should match the type of the property. @Column annotation can also be used with the property to map to a non-default column name.\n\n**@UpdatedBy**\nIf a Supplier is configured using simpleJdbcMapper.setRecordAuditedBySupplier(), it will be used to to set the value for the @UpdatedBy property. The type of the Supplier should match the type of the property. @Column annotation can also be used with the property to map to a non-default column name.\n\n\n Annotation examples:\n\n```java \n\n@Table(name=\"product\")\nclass Product {\n\n @Id(type=IdType.AUTO_GENERATED)\n private Integer productId; \n \n @Column(name=\"product_name\")\n private String name;              // maps to product_name column\n \n @Column\n private String productDescription // defaults to column product_description \n \n @CreatedOn \n private LocalDateTime createdTimestamp;  // defaults to column name created_timestamp. \n                                          // If a Supplier is configured it will use the value from Supplier to populate this property. \n                                          // Make sure Supplier type and property type match\n  \n @CreatedBy\n private String createdByUser;     // defaults to column created_by_user. \n                                   // If a Supplier is configured it will use the value from Supplier to populate this property. \n                                   // Make sure Supplier type and property type match\n  \n @UpdatedOn\n private LocalDateTime updatedAt;  // defaults to column name updated_at.\n                                   // If a Supplier is configured it will use the value from Supplier to populate this property. \n                                   // Make sure Supplier type and property type match\n \n @Column(name=\"last_update_user\")\n @UpdatedBy\n private String updatedBy;         // maps to column last_update_user. \n                                   // If a Supplier is configured it will use the value from Supplier to populate this property. \n                                   // Make sure Supplier type and property type match\n                                  \n   \n @Version\n private Integer version;          // defaults to column version, \n                                   // Property type should be Integer. Used for optimistic locking.\n                                   // Gets incremented every successful update.\n  \n}\n```\n\n## BLOB CLOB mapping\n\n-  Binary large object database columns should be mapped to java type byte[].  \nNo other java type is supported. The 'sqlType' attribute of the @Column annotation with the following values are considered as Binary Large Objects by SimpleJdbcMapper:  \nTypes.BLOB  \nTypes.ARRAY  \nTypes.LONGVARBINARY  \nTypes.VARBINARY  \n\nUse the pertinent SQL type for your database and database column type. \n\n-  Character large object database columns should be mapped to java types String or other CharSequence or char[]. No other java types are supported.  \nThe 'sqlType' attribute of the @Column annotation with the following values are considered as Character Large Objects by SimpeJdbcMapper:  \nTypes.CLOB  \nTypes.NCLOB  \nTypes.LONGVARCHAR  \nTypes.LONGNVARCHAR  \n\nUse the pertinent SQL type for your database and database column type. \n\nIn both the cases above the whole object (image files etc) will be read into memory. For very large objects this could create memory issues and you may want to use InputStream/Reader.  To use InputStream/Reader you will have to use  JdbcTemplate directly since SimpleJdbcMapper does not support these.\n\nSome BLOB/CLOB examples below. Keep in mind depending on the versions of the databases and database column types these could be different.\n\nPostgres:\n\n```\n@Column(sqlType = Types.ARRAY) //mapped to a bytea database column\nprivate byte[] image;\n\n@Column(sqlType = Types.LONGVARCHAR)\nprivate String clobData;\t\n\n```\n\nMySql:\n\n``` \n@Column(sqlType = Types.BLOB)\nprivate byte[] image;\n\n@Column(sqlType = Types.LONGVARCHAR)\nprivate String textData;\n\t\n```\nOracle:\n\n```\n@Column(sqlType = Types.BLOB)\nprivate byte[] image;\n\n@Column(sqlType = Types.CLOB)\nprivate String clobData;\n\t\n```\nSQL Server:\n\n```\n@Column(sqlType = Types.BLOB)\nprivate byte[] image;\n\n@Column(sqlType = Types.CLOB)\nprivate String clobData;\n\n```\n\n## Enum mapping\nEnums should be mapped to a database column which stores strings. It uses the enum.name() to get the string value.\n\n```\npublic enum StatusEnum {\n\tOPEN, CLOSED;\n}\n...\n@Column\nprivate StatusEnum status;  // Mapped to a String column in the database (e.g., value 'OPEN')\n...\n```\n\n## Configuration for auto assigning @CreatedBy, @UpdateBy, @CreatedOn, @UpdatedOn\n```java \n@Bean\npublic SimpleJdbcMapper simpleJdbcMapper(DataSource dataSource) {\n    SimpleJdbcMapper simpleJdbcMapper = new SimpleJdbcMapper(dataSource);\n    // Provide your own custom Supplier. Make Sure the type returned by Supplier matches the type \n    // of the Property you are annotating. Generally 'audited by' is got from a thread local variable \n    // for example when using spring security.\n    simpleJdbcMapper.setRecordAuditedBySupplier(() -\u003e \"tester\");\n    simpleJdbcMapper.setRecordAuditedOnSupplier(() -\u003e LocalDateTime.now());\n    return simpleJdbcMapper;\n}\n```\n \n## Accessing JdbcClient JdbcTemplate\n``` \n JdbcClient jdbcClient = sjm.getJdbcClient();\n JdbcTemplate jdbcTemplate = sjm.getJdbcTemplate();\n NamedParameterJdbcTemplate namedParameterJdbcTemplate = sjm.getNamedParameterJdbcTemplate();\n```\nThere is no requirement that you have to use the underlying JdbcClient/JdbcTemplate for your custom queries. You can create your own JdbcClient/JdbcTemplate and use it. \n\n## Logging\n \nUses the same logging configurations as Spring. In application.properties:\n \n ``` \n \n # log the SQL\n logging.level.org.springframework.jdbc.core.JdbcTemplate=TRACE\n \n # need this to log the INSERT statements\n logging.level.org.springframework.jdbc.core.simple.SimpleJdbcInsert=TRACE\n \n # log the parameters of SQL statement\n logging.level.org.springframework.jdbc.core.StatementCreatorUtils=TRACE\n\n ```\n \n## Limitations\n\n1. @Id can only be mapped to a single database column.  Multi-column ids are not supported.\n2. No support for table/column names with spaces in them.\n3. Primitives not supported. Use the corresponding java wrapper classes in your mappings.\n\nUse JdbcTemplate/JdbcClient directly to handle these cases.\n\n## Upgrading to 2.x from 1.x\nThe 2.x release has removed the dependency on database table column meta-data for mapping totally.\n\nDifference from 1.x:  \n1. SimpleJdbcMapper 2.x tries to infer the correct SQL type from the Java types but some times it cannot. In these cases explicitly declaring the SQL type is a best practice to ensure correctness, improve performance, and correctly handle NULL values. See documentation on @Column(sqlType=\"somesqltype\") and BLOB/CLOB mapping further above on how to figure out and set the SQL type value.\n2. Since 2.x does not use the database table column meta data, it cannot provide  detailed messages on what went wrong with a mapping. Mapping issues will surface through sql errors thrown, which is similar to what happens when using JdbcTemplate/JdbcClient directly.\n3. Primitives not supported. Use corresponding java wrapper classes in your mappings\n\nGenerally the upgrade should be straight forward since API remains the same.  \n\n## TroubleShooting\n\n1.**Connection issues:**\n\nTry to connect to the database using Spring JdbcClient or JdbcTemplate without the SimpleJdbcMapper and issue a simple query. The datasource configuration parameters are exactly the same.\n\n\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspring-jdbc-crud%2Fsimplejdbcmapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspring-jdbc-crud%2Fsimplejdbcmapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspring-jdbc-crud%2Fsimplejdbcmapper/lists"}