Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Spring-data-jdbc not save my Car object?

I'm playing around with spring-data-jdbc and discovered a problem, with I can't solve using Google.

No matter what I try to do, I just can't push a trivial object into the database (Bean1.java:25): carRepository.save(new Car(2L, "BMW", "5"));

Both, without one and with a TransactionManager +@Transactional the database (apparently) does not commit the record.

The code is based on a Postgres database, but you might also simply use a H2 below and get the same result.

Here is the (minimalistic) source code: https://github.com/bitmagier/spring-data-jdbc-sandbox/tree/stackoverflow-question

Can somebody tell me, why the car is not inserted into the database?

like image 902
bitmagier Avatar asked May 16 '18 13:05

bitmagier


People also ask

Does Spring data use JDBC?

In Spring Data JDBC, the entity is required to have an @Id.Spring Data JDBC uses the @Id annotation to identify entities. Similar to Spring Data JPA, Spring Data JDBC uses, by default, a naming strategy that maps Java entities to relational database tables, and attributes to column names.

Which is better Spring JDBC or hibernate?

Hibernate makes a lot of assumptions and forces you to think and code in a certain way. Using JdbcTemplate is easier because it's just a very thin wrapper around JDBC itself. The price here is that you will write thousands of lines of really boring code. Also, you will find that SQL strings are really hard to maintain.

What is difference between JDBC and Spring JDBC?

The Spring JDBC Template has the following advantages compared with standard JDBC. The Spring JDBC template allows to clean-up the resources automatically, e.g. release the database connections. The Spring JDBC template converts the standard JDBC SQLExceptions into RuntimeExceptions.


1 Answers

This is not related to transactions not working. Instead, it's about Spring Data JDBC considering your instance an existing instance that needs updating (instead of inserting).

You can verify this is the problem by activating logging for org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate. You should see an update but no insert.

By default, Spring Data JDBC considers an entity as new when it has an id of an object type and a value of null or of a primitive type (e.g. int or long) and a value of 0. If your entity has an attribute with @Version annotation that attribute will be used to determine if the instance is a new one.

You have the following options in order to make it work:

  1. Set the id to null and configure your database schema so that it will automatically create a new value on insert. After the save your entity instance will contain the generated value from the database.

    Note: Spring Data JDBC will set the id even if it is final in your entity.

  2. Leave the id null and set it in a Before-Save listener to the desired value.

  3. Let your entity implement Persistable. This allows you to control when an entity is considered new. You'll probably need a listener as well so you can let the entity know it is not new any longer.

  4. Beginning with version 1.1 of Spring Data JDBC you'll also be able to use a JdbcAggregateTemplate to do a direct insert, without inspecting the id, see https://jira.spring.io/browse/DATAJDBC-282. Of course, you can do that in a custom method of your repository, as is done in this example: https://github.com/spring-projects/spring-data-examples/pull/441

like image 113
Jens Schauder Avatar answered Sep 19 '22 14:09

Jens Schauder