Jpa failed to use update() when encountered existing record to save - spring

Mysql database table structure:
database table structure
Customer.java class:
#JsonIgnore
#OneToMany(mappedBy = "customer")
private Set<OrderLine> orderLine = new HashSet<>();
Orderline.java class:
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumns({
#JoinColumn(name = "customer_id", referencedColumnName = "customer_id")})
private Customer customer;
Saving data through OrderLineController class:
#PostMapping("/orderLines")
public ResponseEntity<OrderLine> createOrderLine(#RequestBody OrderLine orderLine) {
OrderLine _orderLine = orderLineRepository.save(orderLine);
return new ResponseEntity<>(_orderLine, HttpStatus.CREATED);
}
Here is my Test file:
OrderLine newOL = new OrderLine(order, product);
newOL.setQty(1);
newOL.setCustomer(customer);
ResponseEntity<OrderLine> respOL = restTemplate.postForEntity("/api/orderLines", newOL, OrderLine.class);
assertEquals(HttpStatus.CREATED, respOL.getStatusCode());
I have previously populated an existing data in the Customer table, and now I tried to create new purchase order based on the existing customer.
In my Test file, when the save() function is executed, Jpa sees the "customer" as a new customer, but it was actually returned from the previous method:
ResponseEntity<Customer> getCustomersByCustomerId(String customerId)
Therefore trying to add a record with the same customer_id produced error, but indeed I was hoping the JpaRepository could figured out the customer_id is the same as the existing customer record, but it doesn't. The Jpa repository tried to insert this record into the customer table, thus resulting Duplicate entry error: I have been searching for possible solution for the past 5 days, but the issue still persist. Your help is much appreciated.
2022-10-06 23:36:23.722 DEBUG 16525 --- [o-auto-1-exec-3] org.hibernate.SQL :
insert
into
customer
(email_address, first_name, last_name, phone, customer_id)
values
(?, ?, ?, ?, ?)
Hibernate:
insert
into
customer
(email_address, first_name, last_name, phone, customer_id)
values
(?, ?, ?, ?, ?)
2022-10-06 23:36:23.726 TRACE 16525 --- [o-auto-1-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [sammsonwonder#gmail.com]
2022-10-06 23:36:23.726 TRACE 16525 --- [o-auto-1-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [VARCHAR] - [sammson]
2022-10-06 23:36:23.726 TRACE 16525 --- [o-auto-1-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [VARCHAR] - [wonder]
2022-10-06 23:36:23.726 TRACE 16525 --- [o-auto-1-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [VARCHAR] - [0433233333]
2022-10-06 23:36:23.726 TRACE 16525 --- [o-auto-1-exec-3] o.h.type.descriptor.sql.BasicBinder : binding parameter [5] as [VARCHAR] - [0433233333]
2022-10-06 23:36:23.738 WARN 16525 --- [o-auto-1-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1062, SQLState: 23000
2022-10-06 23:36:23.739 ERROR 16525 --- [o-auto-1-exec-3] o.h.engine.jdbc.spi.SqlExceptionHelper : Duplicate entry '0433233333' for key 'customer.PRIMARY'
2022-10-06 23:36:23.744 INFO 16525 --- [o-auto-1-exec-3] o.h.e.j.b.internal.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
[ERROR] Tests run: 6, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 2.886 s <<< FAILURE! - in dorinca.mm.rest.SavingsTest
[ERROR] create_1st_order_and_1x_product_for_existing_customer Time elapsed: 0.723 s <<< FAILURE!
org.opentest4j.AssertionFailedError: expected: <201 CREATED> but was: <500 INTERNAL_SERVER_ERROR>
at dorinca.mm.rest.SavingsTest.create_1st_order_and_1x_product_for_existing_customer(SavingsTest.java:179)

Related

data.sql script for a H2 database is executing after my application is running for SpringBoot

I am assuming my data.sql script for a H2 database is executing after my application is running, hence, findById()(CRUD Methods) are not fetching any data(NULL). How can I fix this?
Please find my log details:
2020-10-12 18:52:01.361 INFO 30872 --- [ task-1] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default]
2020-10-12 18:52:01.491 INFO 30872 --- [ task-1] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.4.21.Final
2020-10-12 18:52:01.735 INFO 30872 --- [ task-1] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
2020-10-12 18:52:01.956 INFO 30872 --- [ task-1] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Hibernate: drop table if exists monitoring_app CASCADE
Hibernate: create table monitoring_app (id integer generated by default as identity, grep_parameter varchar(255), service_name varchar(255), hostname varchar(255), log_file_name varchar(255), log_file_path varchar(255), max_failed_retries integer not null, restart_sleep_time_secs integer not null, service_failure char(255), primary key (id))
2020-10-12 18:52:02.982 INFO 30872 --- [ task-1] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
2020-10-12 18:52:02.990 INFO 30872 --- [ task-1] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
Hibernate: select monitoring0_.id as id1_0_, monitoring0_.grep_parameter as grep_par2_0_, monitoring0_.service_name as service_3_0_, monitoring0_.hostname as hostname4_0_, monitoring0_.log_file_name as log_file5_0_, monitoring0_.log_file_path as log_file6_0_, monitoring0_.max_failed_retries as max_fail7_0_, monitoring0_.restart_sleep_time_secs as restart_8_0_, monitoring0_.service_failure as service_9_0_ from monitoring_app monitoring0_ where monitoring0_.hostname=?
list is[]
Hibernate: select monitoring0_.id as id1_0_0_, monitoring0_.grep_parameter as grep_par2_0_0_, monitoring0_.service_name as service_3_0_0_, monitoring0_.hostname as hostname4_0_0_, monitoring0_.log_file_name as log_file5_0_0_, monitoring0_.log_file_path as log_file6_0_0_, monitoring0_.max_failed_retries as max_fail7_0_0_, monitoring0_.restart_sleep_time_secs as restart_8_0_0_, monitoring0_.service_failure as service_9_0_0_ from monitoring_app monitoring0_ where monitoring0_.id=?
Hibernate: insert into monitoring_app (id, grep_parameter, service_name, hostname, log_file_name, log_file_path, max_failed_retries, restart_sleep_time_secs, service_failure) values (null, ?, ?, ?, ?, ?, ?, ?, ?)
2020-10-12 18:52:03.679 INFO 30872 --- [ task-2] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
2020-10-12 18:52:03.762 WARN 30872 --- [ restartedMain] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2020-10-12 18:52:04.283 INFO 30872 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2020-10-12 18:52:04.286 INFO 30872 --- [ restartedMain] DeferredRepositoryInitializationListener : Triggering deferred initialization of Spring Data repositories…
2020-10-12 18:52:04.287 INFO 30872 --- [ restartedMain] DeferredRepositoryInitializationListener : Spring Data repositories initialized!
2020-10-12 18:52:04.298 INFO 30872 --- [ restartedMain] c.m.automation.AutomationApplication : Started AutomationApplication in 7.785 seconds (JVM running for 8.729)
UPDATE:
Please find my data.sql
INSERT INTO EXAMPLE VALUES(default ,'a','b','c','d','e','f',1,2,'y');
INSERT INTO EXAMPLE VALUES(default ,'g','h','i','j','k','l',2,3,'n');
This is mu dao class
#Component
public class ExampleDao {
#Autowired
ExampleRepository exampleRepository;
public ArrayList<Example> dbFetchDetails(String var)
{
ArrayList<Example> exampleList = new ArrayList<>();
exampleList= exampleRepository.findByVar(var);
return exampleList;
}}
I extend my Repo with CRUDREPOSITORY and define findByVar()
#Repository
public interface ExampleRepository extends CrudRepository<Example, Integer> {
ArrayList<Example> findByVar(String Var);
}
#Entity
public class Example{
#Id #GeneratedValue(strategy= GenerationType.IDENTITY)
private Integer id;
private String a;
private String b;
private String c;
private String d;
private int e;
private int f;
private String g;
private String h;
private Character i;
//getters setters and contructors added
}
So as you said, your #PostConstruct methods are essentially executing before your data.sql executes and fills your local database with data. A simple way around that is to
Remove your #PostConstruct annotations from the methods that need the data.sql to run
Have the classes that have that were using the #PostConstruct methods implement ApplicationListener<ContextRefreshedEvent>
See example below
#Configuration
class InitConfiguration implements ApplicationListener<ContextRefreshedEvent> {
#Override
public void onApplicationEvent(final ContextRefreshedEvent event) {
init();
}
//Your method that had your #PostConstruct annotation
public void init() {
// The code that needs the data.sql to run
}
}

Spring Data REST - Why hibernate fetches children entity with FetchType.LAZY?

I have a simple use case where I created 2 entities Account & AccountDetail.
These entities have a one-to-one relationship as shown below:
table relationship
The Account entity:
#Entity
#Builder
#AllArgsConstructor
#NoArgsConstructor
#Setter
#Getter
#EqualsAndHashCode
public class Account {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
#OneToOne(mappedBy = "account", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private AccountDetail accountDetail;
}
The AccountDetail entity:
#Entity
#Builder
#AllArgsConstructor
#NoArgsConstructor
#Setter
#Getter
#EqualsAndHashCode
public class AccountDetail {
#Id
private Long id;
#OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) #MapsId
private Account account;
private String firstName;
private String lastName;
}
I am using Spring Boot (v2.3.0) with following dependencies:
- Spring Data JPA: to persist entities using Hibernate
- Rest Repositories: to expose repositories over REST endpoints
The issue is that Hibernate is fetching the AccountDetail entity even though I specified fetch = FetchType.LAZY.
You can see the 2 sql statements in the log:
hibernate log
What I already tried:
Using Projection:
#Projection(types = {Account.class})
public interface AccountProjection {
String getUsername();
}
With the following GET request http://localhost:8080/accounts/1?projection=accountProjection, I get:
{
"username": "warrior24",
"_links": {
"self": {
"href": "http://localhost:8080/accounts/1"
},
"account": {
"href": "http://localhost:8080/accounts/1{?projection}",
"templated": true
},
"accountDetail": {
"href": "http://localhost:8080/accounts/1/accountDetail"
}
}
}
Unfortunately, with this solution, it still makes 2 sql requests.
Using Hibernate Bytecode Enhancement with #LazyToOne(LazyToOneOption.NO_PROXY)
#OneToOne(mappedBy = "account", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#LazyToOne(LazyToOneOption.NO_PROXY)
private AccountDetail accountDetail;
Even this solution does not solve the issue.
Conclusion
I am not sure to understand why hibernate is fetching the child. At the moment it is not a big issue, but if the number of database records gets big it could impact on the performance.
Does anybody have a similar issue and maybe know how to solve it?
Update: Including the debug log for a GET request
2020-05-27 15:23:58.414 INFO 2119 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat-3].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-05-27 15:23:58.414 INFO 2119 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-05-27 15:23:58.414 DEBUG 2119 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Detected StandardServletMultipartResolver
2020-05-27 15:23:58.415 DEBUG 2119 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2020-05-27 15:23:58.415 INFO 2119 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 1 ms
2020-05-27 15:23:58.415 DEBUG 2119 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : GET "/accounts/1", parameters={}
2020-05-27 15:23:58.416 DEBUG 2119 --- [nio-8080-exec-1] o.s.d.r.w.RepositoryRestHandlerMapping : Mapped to org.springframework.data.rest.webmvc.RepositoryEntityController#getItemResource(RootResourceInformation, Serializable, PersistentEntityResourceAssembler, HttpHeaders)
2020-05-27 15:23:58.416 DEBUG 2119 --- [nio-8080-exec-1] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2020-05-27 15:23:58.417 DEBUG 2119 --- [nio-8080-exec-1] stomAnnotationTransactionAttributeSource : Adding transactional method 'findById' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
2020-05-27 15:23:58.417 DEBUG 2119 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(1137877934<open>)] for JPA transaction
2020-05-27 15:23:58.417 DEBUG 2119 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findById]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
2020-05-27 15:23:58.417 DEBUG 2119 --- [nio-8080-exec-1] o.s.jdbc.datasource.DataSourceUtils : Setting JDBC Connection [HikariProxyConnection#646683728 wrapping conn193: url=jdbc:h2:mem:f0df200a-97ea-4e5b-9f80-050ff9a550f7 user=SA] read-only
2020-05-27 15:23:58.417 DEBUG 2119 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle#3a65c273]
2020-05-27 15:23:58.417 DEBUG 2119 --- [nio-8080-exec-1] org.hibernate.SQL : select account0_.id as id1_0_0_, account0_.password as password2_0_0_, account0_.username as username3_0_0_ from account account0_ where account0_.id=?
2020-05-27 15:23:58.417 TRACE 2119 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [1]
2020-05-27 15:23:58.418 DEBUG 2119 --- [nio-8080-exec-1] org.hibernate.SQL : select accountdet0_.account_id as account_3_1_0_, accountdet0_.first_name as first_na1_1_0_, accountdet0_.last_name as last_nam2_1_0_ from account_detail accountdet0_ where accountdet0_.account_id=?
2020-05-27 15:23:58.418 TRACE 2119 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [1]
2020-05-27 15:23:58.418 DEBUG 2119 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
2020-05-27 15:23:58.418 DEBUG 2119 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(1137877934<open>)]
2020-05-27 15:23:58.418 DEBUG 2119 --- [nio-8080-exec-1] o.s.jdbc.datasource.DataSourceUtils : Resetting read-only flag of JDBC Connection [HikariProxyConnection#646683728 wrapping conn193: url=jdbc:h2:mem:f0df200a-97ea-4e5b-9f80-050ff9a550f7 user=SA]
2020-05-27 15:23:58.418 DEBUG 2119 --- [nio-8080-exec-1] o.s.orm.jpa.JpaTransactionManager : Not closing pre-bound JPA EntityManager after transaction
2020-05-27 15:23:58.421 DEBUG 2119 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor : Using 'application/hal+json', given [*/*] and supported [application/hal+json]
2020-05-27 15:23:58.421 DEBUG 2119 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor : Writing [Resource { content: Account(id=1, username=warrior24, password=1234), links: [<http://localhost:8080 (truncated)...]
2020-05-27 15:23:58.421 DEBUG 2119 --- [nio-8080-exec-1] s.d.r.w.j.PersistentEntityJackson2Module : Serializing PersistentEntity org.springframework.data.jpa.mapping.JpaPersistentEntityImpl#45b7be72.
2020-05-27 15:23:58.423 DEBUG 2119 --- [nio-8080-exec-1] .s.ReloadableResourceBundleMessageSource : No properties file found for [classpath:rest-messages] - neither plain properties nor XML
2020-05-27 15:23:58.424 DEBUG 2119 --- [nio-8080-exec-1] .s.ReloadableResourceBundleMessageSource : No properties file found for [classpath:rest-messages_en] - neither plain properties nor XML
2020-05-27 15:23:58.424 DEBUG 2119 --- [nio-8080-exec-1] .s.ReloadableResourceBundleMessageSource : No properties file found for [classpath:rest-messages_en_GB] - neither plain properties nor XML
2020-05-27 15:23:58.426 DEBUG 2119 --- [nio-8080-exec-1] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2020-05-27 15:23:58.426 DEBUG 2119 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 200 OK
Try to use #JsonIgnore annotation that indicates that the annotated method or field is to be ignored by introspection-based serialization and deserialization functionality.
#JsonIgnore
#OneToOne(mappedBy = "account", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private AccountDetail accountDetail;
Try to put #EqualsAndHashCode.Exclude annotation to exclude accountDetail from equals and hashCode methods
#EqualsAndHashCode.Exclude
#OneToOne(mappedBy = "account", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private AccountDetail accountDetail;
SOLUTION (kind of)
Okay I think I found the solution but unfortunately it is not compatible with Spring Data Rest.
By adding optional = false, you can tell hibernate that you will ensure that the child reference will never be null (in my case AccountDetail).
Therefore, it will not need to fetch the child in order to check if it has to create a proxy or assign NULL.
#OneToOne(mappedBy = "account", fetch = FetchType.LAZY, cascade = CascadeType.ALL, optional = false)
#LazyToOne(LazyToOneOption.NO_PROXY)
private AccountDetail accountDetail;
The issue with this solution is that you cannot create a new Account resource using the POST endpoint provided with the #RepositoryRestResource annotation.
Since, it now expects the AccountDetail to be not null, you need to provide the link of this resource in the JSON (which is not existing yet). And you cannot create the AccountDetail resource because it uses as primary key the foreign key from the Account table.

Spring - Same entity detached on the #EventListener but attached in the #Service class

I have following classes in my Spring application: TaskService and DevStartup.
When application starts DevStartup is run, but the Tag("Home") is seen as detached entity on tasksRepository.save(task) which throws detached entity exception during startup.
#Component
#AllArgsConstructor
#Slf4j
#Profile("dev")
public class DevStartup {
private final TagsService tagsService;
private final TagsRepository tagsRepository;
private final TasksRepository tasksRepository;
private final Clock clock;
private final EntityManager entityManager;
#EventListener(ApplicationReadyEvent.class)
public void initializeApplication() {
insertTags();
insertTasks();
}
private void insertTags() {
List<Tag> tags = Arrays.asList(
new Tag("Home")
);
tagsRepository.saveAll(tags);
}
private void insertTasks() {
Task task = new Task("Run a webinar", "Zoom.us", clock.time());
Set<Tag> tagsForTask = Stream.of("Home")
.map(tag -> tagsService.findByName(tag).orElseGet(() -> new Tag(tag)))
.collect(Collectors.toSet());
task.addTags(tagsForTask);
tasksRepository.save(task); // ERROR -> Tag("Home") Entity Detached!!!!!
}
}
At the same time I'm having exact code in the TaskService class and I call it with the same arguments from my REST Controller.
addTask("Task title", "Task description", Stream.of("Home").collect(toSet());
And this time, the Tag("Home") entity is attached
#Service
#RequiredArgsConstructor
public class TasksService {
private final StorageService storageService;
private final TasksRepository tasksRepository;
private final TagsService tagsService;
private final Clock clock;
private final EntityManager entityManager;
public Task addTask(String title, String description, Set<String> tags) {
Task task = new Task(
title,
description,
clock.time()
);
Set<Tag> tagsForTask = tags.stream()
.map(tag -> tagsService.findByName(tag).orElseGet(() -> new Tag(tag)))
.collect(Collectors.toSet());
task.addTags(tagsForTask);
tasksRepository.save(task); // OK -> Tag("Home") Entity Attached
return task;
}
// ...
}
What is the difference between those two and why entity is detached in one case and attached in the other?
I am using Spring Boot 2.1.9 with Hibernate 5 and JPA (Spring Data JPA project).
TagsService.findByName() is just calling TagsRepository.findByNameContainingIgnoreCase:
public interface TagsRepository extends JpaRepository<Tag, Long> {
Optional<Tag> findByNameContainingIgnoreCase(String name);
}
Update
Here are the trace logs from DevStartup. I can spot that session is closed right after fetching the Tag from TagService, and then opened again for saving Task (this is why I'm getting the detached entity exception).
2020-01-25 23:06:46.774 TRACE 33093 --- [ restartedMain] org.hibernate.internal.SessionImpl : Automatically flushing session
2020-01-25 23:06:46.778 TRACE 33093 --- [ restartedMain] org.hibernate.internal.SessionImpl : SessionImpl#afterTransactionCompletion(successful=true, delayed=false)
2020-01-25 23:06:46.779 TRACE 33093 --- [ restartedMain] org.hibernate.internal.SessionImpl : Closing session [d8094673-13fd-4b7e-af38-4aa01afbcaf7]
2020-01-25 23:06:46.789 TRACE 33093 --- [ restartedMain] org.hibernate.internal.SessionImpl : Opened Session [d2c0c551-6523-466f-ab07-a8c1455c62a4] at timestamp: 1579990006789
2020-01-25 23:06:46.848 DEBUG 33093 --- [ restartedMain] org.hibernate.SQL : select tag0_.id as id1_2_, tag0_.name as name2_2_ from tag tag0_ where upper(tag0_.name) like upper(?) escape ?
Hibernate: select tag0_.id as id1_2_, tag0_.name as name2_2_ from tag tag0_ where upper(tag0_.name) like upper(?) escape ?
2020-01-25 23:06:46.850 TRACE 33093 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [%Home%]
2020-01-25 23:06:46.850 TRACE 33093 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [CHAR] - [\]
2020-01-25 23:06:46.855 TRACE 33093 --- [ restartedMain] org.hibernate.internal.SessionImpl : Closing session [d2c0c551-6523-466f-ab07-a8c1455c62a4]
2020-01-25 23:06:46.860 TRACE 33093 --- [ restartedMain] org.hibernate.internal.SessionImpl : Opened Session [6caeb288-a608-4aa7-a5f9-091c69900815] at timestamp: 1579990006860
2020-01-25 23:06:46.867 DEBUG 33093 --- [ restartedMain] org.hibernate.SQL : insert into task (id, uuid, created_at, description, title) values (null, ?, ?, ?, ?)
Hibernate: insert into task (id, uuid, created_at, description, title) values (null, ?, ?, ?, ?)
2020-01-25 23:06:46.868 TRACE 33093 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [fc9c993b-eccf-45ff-b49a-12498b6e62eb]
2020-01-25 23:06:46.868 TRACE 33093 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [TIMESTAMP] - [2020-01-25T23:06:46.785455]
2020-01-25 23:06:46.870 TRACE 33093 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [VARCHAR] - [Zoom.us]
2020-01-25 23:06:46.872 TRACE 33093 --- [ restartedMain] o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [VARCHAR] - [Run a webinar]
2020-01-25 23:06:46.879 TRACE 33093 --- [ restartedMain] org.hibernate.internal.SessionImpl : SessionImpl#afterTransactionCompletion(successful=false, delayed=false)
2020-01-25 23:06:46.880 TRACE 33093 --- [ restartedMain] org.hibernate.internal.SessionImpl : Closing session [6caeb288-a608-4aa7-a5f9-091c69900815]
2020-01-25 23:06:46.900 ERROR 33093 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
Below are the logs when running code from TaskService. The session is not closed between fetching tags and saving tasks.
2020-01-25 23:10:24.966 TRACE 33194 --- [ restartedMain] org.hibernate.internal.SessionImpl : Closing session [f3ea3806-3c65-4269-81b4-ba8bc1abf2af]
2020-01-25 23:10:55.518 INFO 33194 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2020-01-25 23:10:55.519 INFO 33194 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2020-01-25 23:10:55.533 INFO 33194 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 14 ms
2020-01-25 23:10:55.553 TRACE 33194 --- [nio-8080-exec-1] org.hibernate.internal.SessionImpl : Opened Session [61d3d232-2d92-4002-8e4c-cedb0278a2e9] at timestamp: 1579990255552
2020-01-25 23:10:55.858 INFO 33194 --- [nio-8080-exec-1] p.s.t.tasks.boundary.TasksController : Storing new task: CreateTaskRequest(title=Dokończyć Moduł 8, description=Jpa i Hibernate cz. 2, attachmentComment=null, tags=[Home])
2020-01-25 23:10:55.914 DEBUG 33194 --- [nio-8080-exec-1] org.hibernate.SQL : select tag0_.id as id1_2_, tag0_.name as name2_2_ from tag tag0_ where upper(tag0_.name) like upper(?) escape ?
Hibernate: select tag0_.id as id1_2_, tag0_.name as name2_2_ from tag tag0_ where upper(tag0_.name) like upper(?) escape ?
2020-01-25 23:10:55.920 TRACE 33194 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [%Home%]
2020-01-25 23:10:55.920 TRACE 33194 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [CHAR] - [\]
2020-01-25 23:10:59.218 DEBUG 33194 --- [nio-8080-exec-1] org.hibernate.SQL : insert into task (id, uuid, created_at, description, title) values (null, ?, ?, ?, ?)
Hibernate: insert into task (id, uuid, created_at, description, title) values (null, ?, ?, ?, ?)
2020-01-25 23:10:59.218 TRACE 33194 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [bac8dacb-9424-4c6e-9a3a-860973ebc350]
2020-01-25 23:10:59.219 TRACE 33194 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [TIMESTAMP] - [2020-01-25T23:10:55.878153]
2020-01-25 23:10:59.223 TRACE 33194 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [VARCHAR] - [Jpa i Hibernate cz. 2]
2020-01-25 23:10:59.224 TRACE 33194 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [4] as [VARCHAR] - [Dokończyć Moduł 8]
2020-01-25 23:10:59.244 TRACE 33194 --- [nio-8080-exec-1] org.hibernate.internal.SessionImpl : SessionImpl#beforeTransactionCompletion()
2020-01-25 23:10:59.244 TRACE 33194 --- [nio-8080-exec-1] org.hibernate.internal.SessionImpl : Automatically flushing session
2020-01-25 23:10:59.262 DEBUG 33194 --- [nio-8080-exec-1] org.hibernate.SQL : insert into tags_tasks (task_id, tag_id) values (?, ?)
Hibernate: insert into tags_tasks (task_id, tag_id) values (?, ?)
2020-01-25 23:10:59.263 TRACE 33194 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [BIGINT] - [1]
2020-01-25 23:10:59.264 TRACE 33194 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [BIGINT] - [1]
2020-01-25 23:10:59.273 TRACE 33194 --- [nio-8080-exec-1] org.hibernate.internal.SessionImpl : SessionImpl#afterTransactionCompletion(successful=true, delayed=false)
Most likely, you have Open Session In View enabled
If you are running a web application, Spring Boot by default registers OpenEntityManagerInViewInterceptor to apply the “Open EntityManager in View” pattern, to allow for lazy loading in web views. If you do not want this behavior, you should set spring.jpa.open-in-view to false in your application.properties.
This will open the session when request starts and and closes it after the request processing is done. The interceptor is run for web request, but not in case of ApplicationReadyEvent event listener.
You may want to use #Transactional to extend the lifetime of the session when you are not relying on open session in view. See https://stackoverflow.com/a/24713402/1570854:
In Spring, there is a one-to-one correspondence between the business transaction demarcated by #Transactional, and the hibernate Session.
That is, when a business transaction is begun by invoking a #Transactional method, the hibernate session is created (a TransactionManager may delay the actual creation until the session is first used). Once that method completes, the business transaction is committed or rolled back, which closes the hibernate session.
Many consider open session in view to be an anti-pattern: https://vladmihalcea.com/the-open-session-in-view-anti-pattern/

Spring-boot multiple databases - spring inserts data but only saves to one db

I've really been struggling with a multiple (2) db setup in springboot. I've spent countless of hours and followed many examples and I've read the complete documentation.
I find it hard to decide what should be added in my code because there are so many examples with different solutions around. There's Spring, Spring-boot, hibernate, jpa, beans, xml files, annotations, corrupt dependencies.
I've come up with a piece of code that doesn't give errors and saves my data. But, only the data to the primary database gets saved. The insert in the second db is happening according to the sql trace but no commit. What's going on here?
I also made a simple controller class to insert data with an http request, but it had the same results: only user in db1 gets saved, product in db2 doesn't.
If anybody has any clue it would be greatly appreciated. It's driving me nuts!
I realize this is just a simple piece of code, but it's test to see if I can use this approach in a bigger project.
Thanks!
the configuration:
import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import com.multidb.db1.enitities.User;
import com.multidb.db2.entities.Product;
import javax.sql.DataSource;
#EnableJpaRepositories
public class DbConfiguration {
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties firstDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.datasource.configuration")
public HikariDataSource firstDataSource() {
return firstDataSourceProperties().initializeDataSourceBuilder()
.type(HikariDataSource.class).build();
}
#Bean
#ConfigurationProperties("spring.datasource2")
public DataSourceProperties secondDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("spring.datasource2.configuration")
public BasicDataSource secondDataSource() {
return secondDataSourceProperties().initializeDataSourceBuilder()
.type(BasicDataSource.class).build();
}
//////
#Primary
#Bean
public LocalContainerEntityManagerFactoryBean userEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(firstDataSource())
.packages("db1")//User.class
.persistenceUnit("users")
.build();
}
#Bean
public LocalContainerEntityManagerFactoryBean productEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(secondDataSource())
.packages("db2")//Product.class
.persistenceUnit("products")
.build();
}
}
the applicaton.properties file
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
spring.datasource.url=jdbc:mysql://localhost/db1?autoReconnect=true&useSSL=false
spring.datasource.username=user
spring.datasource.password=pass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.configuration.maximum-pool-size=30
spring.datasource2.url=jdbc:mysql://localhost/db2?autoReconnect=true&useSSL=false
spring.datasource2.username=user
spring.datasource2.password=pass
spring.datasource2.driver-class-name=com.mysql.jdbc.Driver
spring.datasource2.max-total=30
a simple user class
import javax.persistence.*;
#Entity
#Table
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public User() {
//
}
}
and the product class
import javax.persistence.*;
#Entity
#Table
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private double price;
public Product(String name, double price) {
this.name = name;
this.price = price;
}
public Product() {
//
}
}
a user repo
import org.springframework.data.repository.CrudRepository;
import com.multidb.db1.enitities.User;
import org.springframework.transaction.annotation.Transactional;
#Transactional
public interface UserRepository extends CrudRepository<User, Long> {
//
}
a product repo
import com.multidb.db2.entities.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.CrudRepository;
public interface ProductRepository extends CrudRepository<Product, Long> {
//
}
a simple datainit class to write something to the db
import com.multidb.db1.repositories.UserRepository;
import com.multidb.db1.enitities.User;
import com.multidb.db2.entities.Product;
import com.multidb.db2.repositories.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
#Component
public class InitData implements ApplicationRunner {
#Autowired
private ProductRepository productRepository;
#Autowired
private UserRepository userRepository;
#Autowired
public InitData(){}
#Override
public void run(ApplicationArguments args) throws Exception {
addUser("Johnny", "Depp");
addProduct("Booze", 5.0);
}
private void addUser(String firstname, String lastname){
User user = new User(firstname, lastname);
userRepository.save(user);
}
private void addProduct(String name, double price){
Product product = new Product(name, price);
productRepository.save(product);
}
}
the Maven dependencies
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>
</dependencies>
Last but not least the ouput
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.3.RELEASE)
2019-04-02 13:20:09.084 INFO 47275 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode.
2019-04-02 13:20:09.147 INFO 47275 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 56ms. Found 2 repository interfaces.
2019-04-02 13:20:09.466 INFO 47275 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$84774c02] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-04-02 13:20:09.765 INFO 47275 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2019-04-02 13:20:09.795 INFO 47275 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2019-04-02 13:20:09.796 INFO 47275 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.16]
2019-04-02 13:20:09.805 INFO 47275 --- [ main] o.a.catalina.core.AprLifecycleListener : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/Users/Fdoe/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.]
2019-04-02 13:20:09.884 INFO 47275 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2019-04-02 13:20:09.885 INFO 47275 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1367 ms
2019-04-02 13:20:10.114 INFO 47275 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-04-02 13:20:10.327 INFO 47275 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-04-02 13:20:10.368 INFO 47275 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: default
...]
2019-04-02 13:20:10.423 INFO 47275 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5.3.7.Final}
2019-04-02 13:20:10.424 INFO 47275 --- [ main] org.hibernate.cfg.Environment : HHH000206: hibernate.properties not found
2019-04-02 13:20:10.553 INFO 47275 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.0.4.Final}
2019-04-02 13:20:10.684 INFO 47275 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
2019-04-02 13:20:11.209 DEBUG 47275 --- [ main] org.hibernate.SQL : drop table if exists hibernate_sequence
Hibernate: drop table if exists hibernate_sequence
2019-04-02 13:20:11.220 DEBUG 47275 --- [ main] org.hibernate.SQL : drop table if exists product
Hibernate: drop table if exists product
2019-04-02 13:20:11.222 DEBUG 47275 --- [ main] org.hibernate.SQL : drop table if exists user
Hibernate: drop table if exists user
2019-04-02 13:20:11.225 DEBUG 47275 --- [ main] org.hibernate.SQL : create table hibernate_sequence (next_val bigint) engine=MyISAM
Hibernate: create table hibernate_sequence (next_val bigint) engine=MyISAM
2019-04-02 13:20:11.228 DEBUG 47275 --- [ main] org.hibernate.SQL : insert into hibernate_sequence values ( 1 )
Hibernate: insert into hibernate_sequence values ( 1 )
2019-04-02 13:20:11.230 DEBUG 47275 --- [ main] org.hibernate.SQL : insert into hibernate_sequence values ( 1 )
Hibernate: insert into hibernate_sequence values ( 1 )
2019-04-02 13:20:11.231 DEBUG 47275 --- [ main] org.hibernate.SQL : create table product (id bigint not null, name varchar(255), price double precision not null, primary key (id)) engine=MyISAM
Hibernate: create table product (id bigint not null, name varchar(255), price double precision not null, primary key (id)) engine=MyISAM
2019-04-02 13:20:11.235 DEBUG 47275 --- [ main] org.hibernate.SQL : create table user (id bigint not null, first_name varchar(255), last_name varchar(255), primary key (id)) engine=MyISAM
Hibernate: create table user (id bigint not null, first_name varchar(255), last_name varchar(255), primary key (id)) engine=MyISAM
2019-04-02 13:20:11.239 INFO 47275 --- [ main] o.h.t.schema.internal.SchemaCreatorImpl : HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl#3a7c678b'
2019-04-02 13:20:11.241 INFO 47275 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2019-04-02 13:20:11.651 INFO 47275 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2019-04-02 13:20:11.695 WARN 47275 --- [ main] aWebConfiguration$JpaWebMvcConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2019-04-02 13:20:11.889 INFO 47275 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-04-02 13:20:11.891 INFO 47275 --- [ main] com.fdoe.multidb.Application : Started Application in 3.92 seconds (JVM running for 4.308)
2019-04-02 13:20:11.913 DEBUG 47275 --- [ main] org.hibernate.SQL : select next_val as id_val from hibernate_sequence for update
Hibernate: select next_val as id_val from hibernate_sequence for update
2019-04-02 13:20:11.928 DEBUG 47275 --- [ main] org.hibernate.SQL : update hibernate_sequence set next_val= ? where next_val=?
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
2019-04-02 13:20:11.948 DEBUG 47275 --- [ main] org.hibernate.SQL : insert into user (first_name, last_name, id) values (?, ?, ?)
Hibernate: insert into user (first_name, last_name, id) values (?, ?, ?)
2019-04-02 13:20:11.950 TRACE 47275 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [Johnny]
2019-04-02 13:20:11.950 TRACE 47275 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [VARCHAR] - [Depp]
2019-04-02 13:20:11.951 TRACE 47275 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [1]
2019-04-02 13:20:11.957 DEBUG 47275 --- [ main] org.hibernate.SQL : select next_val as id_val from hibernate_sequence for update
Hibernate: select next_val as id_val from hibernate_sequence for update
2019-04-02 13:20:11.958 DEBUG 47275 --- [ main] org.hibernate.SQL : update hibernate_sequence set next_val= ? where next_val=?
Hibernate: update hibernate_sequence set next_val= ? where next_val=?
2019-04-02 13:20:11.959 DEBUG 47275 --- [ main] org.hibernate.SQL : insert into product (name, price, id) values (?, ?, ?)
Hibernate: insert into product (name, price, id) values (?, ?, ?)
2019-04-02 13:20:11.959 TRACE 47275 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [1] as [VARCHAR] - [Booze]
2019-04-02 13:20:11.960 TRACE 47275 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [2] as [DOUBLE] - [5.0]
2019-04-02 13:20:11.960 TRACE 47275 --- [ main] o.h.type.descriptor.sql.BasicBinder : binding parameter [3] as [BIGINT] - [2]
db1 - terminal/command line output
mysql> select * from user;
+----+------------+-----------+
| id | first_name | last_name |
+----+------------+-----------+
| 1 | Johnny | Depp |
+----+------------+-----------+
1 row in set (0.00 sec)
mysql>
db2 - terminal/command line output
mysql> select * from product;
Empty set (0.01 sec)
mysql>
You have not included Product Repository and User Repository class,please check the annotation in the class
Did you use Entity Manager
if Yes then
Did you use #PersistenceContext annotation for the entity manager
please follow the below example,try to run it on your local by just copy pasting the code and seeing the configuration
Spring Boot + JPA
if you have used CRUD Repository
You can refer to the below code
Spring Boot+CRUD Repository+JPA
Both are running in my local

Spring Boot Hibernate Syntax Error in SQL Statement

I've modified the Spring Boot JPA Data example (https://github.com/spring-guides/gs-accessing-data-jpa.git) slightly adding an Order entity and a corresponding one to many mapping to it from the customer. When I run the example there are several Syntax Error in SQL Statement lines logged by Hibernate. I'm trying to figure out why? I've pasted the code for the entities and the console output from the application below.
package hello;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
#Entity
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
#OneToMany(mappedBy="customer")
private List<Order> orders;
protected Customer() {}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
#Override
public String toString() {
return String.format(
"Customer[id=%d, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
}
And a corresponding Order entity:
package hello;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
#Entity
public class Order {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
protected Order() {}
double amount;
#ManyToOne
Customer customer;
}
And the console output:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.1.10.RELEASE)
2015-01-16 08:56:53.116 INFO 27810 --- [ main] hello.Application : Starting Application on MKI with PID 27810 (/home/ole/Documents/workspace-sts-3.6.3.RELEASE/gs-accessing-data-jpa-complete/target/classes started by ole in /home/ole/Documents/workspace-sts-3.6.3.RELEASE/gs-accessing-data-jpa-complete)
2015-01-16 08:56:53.149 INFO 27810 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext#5d59e6f1: startup date [Fri Jan 16 08:56:53 CST 2015]; root of context hierarchy
2015-01-16 08:56:54.253 INFO 27810 --- [ main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2015-01-16 08:56:54.269 INFO 27810 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: default
...]
2015-01-16 08:56:54.320 INFO 27810 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {4.3.7.Final}
2015-01-16 08:56:54.322 INFO 27810 --- [ main] org.hibernate.cfg.Environment : HHH000205: Loaded properties from resource hibernate.properties: {hibernate.connection.charSet=UTF-8, hibernate.dialect=org.hibernate.dialect.H2Dialect, hibernate.show_sql=true, hibernate.export.schema.delimiter=;, hibernate.bytecode.use_reflection_optimizer=false, hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy}
2015-01-16 08:56:54.322 INFO 27810 --- [ main] org.hibernate.cfg.Environment : HHH000021: Bytecode provider name : javassist
2015-01-16 08:56:54.462 INFO 27810 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {4.0.5.Final}
2015-01-16 08:56:54.499 INFO 27810 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
2015-01-16 08:56:54.591 INFO 27810 --- [ main] o.h.h.i.ast.ASTQueryTranslatorFactory : HHH000397: Using ASTQueryTranslatorFactory
2015-01-16 08:56:54.751 INFO 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000227: Running hbm2ddl schema export
Hibernate: alter table order drop constraint FK_m6q2ofkj1g5aobtb2p00ajpqg if exists
2015-01-16 08:56:54.752 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: alter table order drop constraint FK_m6q2ofkj1g5aobtb2p00ajpqg if exists
2015-01-16 08:56:54.753 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : Syntax error in SQL statement "ALTER TABLE ORDER[*] DROP CONSTRAINT FK_M6Q2OFKJ1G5AOBTB2P00AJPQG IF EXISTS "; expected "identifier"; SQL statement:
alter table order drop constraint FK_m6q2ofkj1g5aobtb2p00ajpqg if exists [42001-176]
Hibernate: drop table customer if exists
Hibernate: drop table order if exists
2015-01-16 08:56:54.753 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: drop table order if exists
2015-01-16 08:56:54.753 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : Syntax error in SQL statement "DROP TABLE ORDER[*] IF EXISTS "; expected "identifier"; SQL statement:
drop table order if exists [42001-176]
Hibernate: create table customer (id bigint generated by default as identity, first_name varchar(255), last_name varchar(255), primary key (id))
Hibernate: create table order (id bigint generated by default as identity, amount double not null, customer_id bigint, primary key (id))
2015-01-16 08:56:54.756 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: create table order (id bigint generated by default as identity, amount double not null, customer_id bigint, primary key (id))
2015-01-16 08:56:54.756 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : Syntax error in SQL statement "CREATE TABLE ORDER[*] (ID BIGINT GENERATED BY DEFAULT AS IDENTITY, AMOUNT DOUBLE NOT NULL, CUSTOMER_ID BIGINT, PRIMARY KEY (ID)) "; expected "identifier"; SQL statement:
create table order (id bigint generated by default as identity, amount double not null, customer_id bigint, primary key (id)) [42001-176]
Hibernate: alter table order add constraint FK_m6q2ofkj1g5aobtb2p00ajpqg foreign key (customer_id) references customer
2015-01-16 08:56:54.757 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: alter table order add constraint FK_m6q2ofkj1g5aobtb2p00ajpqg foreign key (customer_id) references customer
2015-01-16 08:56:54.757 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : Syntax error in SQL statement "ALTER TABLE ORDER[*] ADD CONSTRAINT FK_M6Q2OFKJ1G5AOBTB2P00AJPQG FOREIGN KEY (CUSTOMER_ID) REFERENCES CUSTOMER "; expected "identifier"; SQL statement:
alter table order add constraint FK_m6q2ofkj1g5aobtb2p00ajpqg foreign key (customer_id) references customer [42001-176]
2015-01-16 08:56:54.757 INFO 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000230: Schema export complete
2015-01-16 08:56:55.085 INFO 27810 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2015-01-16 08:56:55.102 INFO 27810 --- [ main] hello.Application : Started Application in 2.286 seconds (JVM running for 2.604)
Hibernate: insert into customer (id, first_name, last_name) values (null, ?, ?)
Hibernate: insert into customer (id, first_name, last_name) values (null, ?, ?)
Hibernate: insert into customer (id, first_name, last_name) values (null, ?, ?)
Hibernate: insert into customer (id, first_name, last_name) values (null, ?, ?)
Hibernate: insert into customer (id, first_name, last_name) values (null, ?, ?)
Hibernate: select customer0_.id as id1_0_, customer0_.first_name as first_na2_0_, customer0_.last_name as last_nam3_0_ from customer customer0_
Customers found with findAll():
-------------------------------
Customer[id=1, firstName='Jack', lastName='Bauer']
Customer[id=2, firstName='Chloe', lastName='O'Brian']
Customer[id=3, firstName='Kim', lastName='Bauer']
Customer[id=4, firstName='David', lastName='Palmer']
Customer[id=5, firstName='Michelle', lastName='Dessler']
Hibernate: select customer0_.id as id1_0_0_, customer0_.first_name as first_na2_0_0_, customer0_.last_name as last_nam3_0_0_ from customer customer0_ where customer0_.id=?
Customer found with findOne(1L):
--------------------------------
Customer[id=1, firstName='Jack', lastName='Bauer']
Hibernate: select customer0_.id as id1_0_, customer0_.first_name as first_na2_0_, customer0_.last_name as last_nam3_0_ from customer customer0_ where customer0_.last_name=?
Customer found with findByLastName('Bauer'):
--------------------------------------------
Customer[id=1, firstName='Jack', lastName='Bauer']
Customer[id=3, firstName='Kim', lastName='Bauer']
Hibernate: select customer0_.id as id1_0_, customer0_.first_name as first_na2_0_, customer0_.last_name as last_nam3_0_ from customer customer0_
Hibernate: delete from customer where id=?
Hibernate: delete from customer where id=?
Hibernate: delete from customer where id=?
Hibernate: delete from customer where id=?
Hibernate: delete from customer where id=?
2015-01-16 08:56:55.258 INFO 27810 --- [ main] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext#5d59e6f1: startup date [Fri Jan 16 08:56:53 CST 2015]; root of context hierarchy
2015-01-16 08:56:55.259 INFO 27810 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Unregistering JMX-exposed beans on shutdown
2015-01-16 08:56:55.260 INFO 27810 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2015-01-16 08:56:55.261 INFO 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000227: Running hbm2ddl schema export
Hibernate: alter table order drop constraint FK_m6q2ofkj1g5aobtb2p00ajpqg if exists
2015-01-16 08:56:55.261 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: alter table order drop constraint FK_m6q2ofkj1g5aobtb2p00ajpqg if exists
2015-01-16 08:56:55.261 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : Syntax error in SQL statement "ALTER TABLE ORDER[*] DROP CONSTRAINT FK_M6Q2OFKJ1G5AOBTB2P00AJPQG IF EXISTS "; expected "identifier"; SQL statement:
alter table order drop constraint FK_m6q2ofkj1g5aobtb2p00ajpqg if exists [42001-176]
Hibernate: drop table customer if exists
Hibernate: drop table order if exists
2015-01-16 08:56:55.263 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: drop table order if exists
2015-01-16 08:56:55.263 ERROR 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : Syntax error in SQL statement "DROP TABLE ORDER[*] IF EXISTS "; expected "identifier"; SQL statement:
drop table order if exists [42001-176]
2015-01-16 08:56:55.263 INFO 27810 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000230: Schema export complete
Thoughts?
TIA,
- Ole
Try change your Order entity please:
package hello;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "order_table")
public class Order {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
protected Order() {}
double amount;
#ManyToOne
Customer customer;
}
Explanation:
Pay attention on #Table annotation. Using this annotation I've specified table name as order_table. In your case by default hibernate tried to generate table order. ORDER is service word in any sql. Exception appeared because hibernate was generating *** statement for the order table but db expected table name not service word order.
I had the exact same problem with an Order entity, solved defining explicitly the table name.
#Entity
#Table(name = "order_table")
class Order(
#Id
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid2")
val orderId: String,
val customerId: String,
...
)
I had the same issue with a column named order but I was unable to change it. Adding backticks to the column annotation solved it.
#Column(name = "`ORDER`")
val order: String

Resources