issue with #oneToMany bi-directional mapping in springboot - java

I am trying to retrieve data from 2 tables in MySql using spring boot and hibernate #OneToMany bi-directional mapping. But am getting this error among others:
No identifier specified for entity: com.dafe.spring.applogger.entity.Action
Please Check the error trace below:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-03-14 18:56:59.251 ERROR 8200 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: No identifier specified for entity: com.dafe.spring.applogger.entity.Action
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1771) ~[spring-beans-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593) ~[spring-beans-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1105) ~[spring-context-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867) ~[spring-context-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.1.13.RELEASE.jar:2.1.13.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744) [spring-boot-2.1.13.RELEASE.jar:2.1.13.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391) [spring-boot-2.1.13.RELEASE.jar:2.1.13.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) [spring-boot-2.1.13.RELEASE.jar:2.1.13.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) [spring-boot-2.1.13.RELEASE.jar:2.1.13.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1204) [spring-boot-2.1.13.RELEASE.jar:2.1.13.RELEASE]
at com.dafe.spring.applogger.AppLoggerApplication.main(AppLoggerApplication.java:10) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:1.8.0_161]
at java.lang.reflect.Method.invoke(Unknown Source) ~[na:1.8.0_161]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) [spring-boot-devtools-2.1.13.RELEASE.jar:2.1.13.RELEASE]
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: com.dafe.spring.applogger.entity.Action
at org.hibernate.cfg.InheritanceState.determineDefaultAccessType(InheritanceState.java:266) ~[hibernate-core-5.3.15.Final.jar:5.3.15.Final]
at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:211) ~[hibernate-core-5.3.15.Final.jar:5.3.15.Final]
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:775) ~[hibernate-core-5.3.15.Final.jar:5.3.15.Final]
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:250) ~[hibernate-core-5.3.15.Final.jar:5.3.15.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:231) ~[hibernate-core-5.3.15.Final.jar:5.3.15.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:274) ~[hibernate-core-5.3.15.Final.jar:5.3.15.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1215) ~[hibernate-core-5.3.15.Final.jar:5.3.15.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1246) ~[hibernate-core-5.3.15.Final.jar:5.3.15.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391) ~[spring-orm-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:378) ~[spring-orm-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1830) ~[spring-beans-5.1.14.RELEASE.jar:5.1.14.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1767) ~[spring-beans-5.1.14.RELEASE.jar:5.1.14.RELEASE]
... 21 common frames omitted
the class the error is pointing to is below but I don't seem to know what the problem is. Find below is the com.dafe.spring.applogger.entity.Action class :
package com.dafe.spring.applogger.entity;
import java.sql.Timestamp;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.springframework.data.annotation.Id;
#Entity
#Table(name="action")
public class Action {
//declare & annotate your fields
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="time")
private Timestamp logTime;
#Column(name="type")
private String logType;
#Column(name="log_id")
private int userLogId;
#ManyToOne
#JoinColumn(name="log_id")
private UserLog userLog;
public Action(int id, Timestamp logTime, String logType, int userLogId, UserLog userLog) {
this.id = id;
this.logTime = logTime;
this.logType = logType;
this.userLogId = userLogId;
this.userLog = userLog;
}
//create and generate constructor
public Action() {
}
public Action(Timestamp logTime, String logType, int userLogId) {
this.logTime = logTime;
this.logType = logType;
this.userLogId = userLogId;
}
//generate getters and setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Timestamp getLogTime() {
return logTime;
}
public void setLogTime(Timestamp logTime) {
this.logTime = logTime;
}
public String getLogType() {
return logType;
}
public void setLogType(String logType) {
this.logType = logType;
}
public int getLogId() {
return userLogId;
}
public void setLogId(int logId) {
this.userLogId = logId;
}
public UserLog userLog() {
return userLog;
}
public void setLogs(UserLog userLog) {
this.userLog = userLog;
}
//generate toString
#Override
public String toString() {
return "Action [id=" + id + ", logTime=" + logTime + ", logType=" + logType + ", userLogId=" + userLogId + "]";
}
}
The action class is supposed to fetch data from database and has a foreign key relationship with class UserLog.
package com.dafe.spring.applogger.entity;
import java.util.ArrayList;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name="log")
public class UserLog {
//define field
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
private int id;
#Column(name="user_id")
private String userId;
#Column(name="session_id")
private String sessionId;
#OneToMany(mappedBy="log",cascade=CascadeType.ALL)
private ArrayList<Action>action;
//define constructors
public UserLog(String userId, String sessionId) {
this.userId = userId;
this.sessionId = sessionId;
}
//define getters and setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getSessionId() {
return sessionId;
}
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}
public ArrayList<Action> getAction() {
return action;
}
public void setAction(ArrayList<Action> action) {
this.action = action;
}
//convenience method for Action
public void addAction(Action tempAction) {
if (action == null) {
action = new ArrayList<>();
}
action.add(tempAction);
}
//define toString
#Override
public String toString() {
return "Log [id=" + id + ", userId=" + userId + ", sessionId=" + sessionId + "]";
}
}
please help me figure out the problem and a possible solution. Thanks.

You have imported the Id from the wrong package.This error can be thrown when you import a different library for #Id than javax.persistance.Id ;
So change
import org.springframework.data.annotation.Id;
To
import javax.persistence.Id
Refer this thread

I think an issue is related to this mapping:
#OneToMany(mappedBy="log",cascade=CascadeType.ALL)
private ArrayList<Action>action;
mappedBy points to the name of the property on the 'owning' side. So in your case you should specify mappedBy="userLog" as it's defined in Action class
#ManyToOne
#JoinColumn(name="log_id")
private UserLog userLog;

Related

Error executing DDL postgres Java spring boot API

I'm developing a request API in java spring boot, I developed my post but when testing it returns the 400 bad request error and the following error in the terminal
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table restaurant_orders (id uuid not null, address varchar(25) not null, block varchar(5), customer_name varchar(11) not null, door_number varchar(10) not null, order varchar(30) not null, phone_number varchar(15) not null, price float4 not null, registration_date timestamp(6) not null, primary key (id))" via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlString(AbstractSchemaMigrator.java:587) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlStrings(AbstractSchemaMigrator.java:532) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.createTable(AbstractSchemaMigrator.java:307) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.tool.schema.internal.GroupedSchemaMigratorImpl.performTablesMigration(GroupedSchemaMigratorImpl.java:79) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.performMigration(AbstractSchemaMigrator.java:225) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:126) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:284) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:143) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at java.base/java.util.HashMap.forEach(HashMap.java:1429) ~[na:na]
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:140) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:336) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:415) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1425) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) ~[spring-orm-6.0.4.jar:6.0.4]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) ~[spring-orm-6.0.4.jar:6.0.4]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.0.4.jar:6.0.4]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.0.4.jar:6.0.4]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:352) ~[spring-orm-6.0.4.jar:6.0.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1797) ~[spring-beans-6.0.4.jar:6.0.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1747) ~[spring-beans-6.0.4.jar:6.0.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.0.4.jar:6.0.4]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) ~[spring-beans-6.0.4.jar:6.0.4]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[spring-beans-6.0.4.jar:6.0.4]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.0.4.jar:6.0.4]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[spring-beans-6.0.4.jar:6.0.4]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.0.4.jar:6.0.4]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1130) ~[spring-context-6.0.4.jar:6.0.4]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:905) ~[spring-context-6.0.4.jar:6.0.4]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:584) ~[spring-context-6.0.4.jar:6.0.4]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.0.2.jar:3.0.2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[spring-boot-3.0.2.jar:3.0.2]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432) ~[spring-boot-3.0.2.jar:3.0.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-3.0.2.jar:3.0.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[spring-boot-3.0.2.jar:3.0.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[spring-boot-3.0.2.jar:3.0.2]
at com.api.order_control.OrderControlApplication.main(OrderControlApplication.java:12) ~[classes/:na]
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near "order"
Position: 169
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2676) ~[postgresql-42.5.1.jar:42.5.1]
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2366) ~[postgresql-42.5.1.jar:42.5.1]
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:356) ~[postgresql-42.5.1.jar:42.5.1]
at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:496) ~[postgresql-42.5.1.jar:42.5.1]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:413) ~[postgresql-42.5.1.jar:42.5.1]
at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:333) ~[postgresql-42.5.1.jar:42.5.1]
at org.postgresql.jdbc.PgStatement.executeCachedSql(PgStatement.java:319) ~[postgresql-42.5.1.jar:42.5.1]
at org.postgresql.jdbc.PgStatement.executeWithFlags(PgStatement.java:295) ~[postgresql-42.5.1.jar:42.5.1]
at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:290) ~[postgresql-42.5.1.jar:42.5.1]
at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:94) ~[HikariCP-5.0.1.jar:na]
at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) ~[HikariCP-5.0.1.jar:na]
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54) ~[hibernate-core-6.1.6.Final.jar:6.1.6.Final]
... 36 common frames omitted
I saw in some searches that the name "order" could be causing a problem in the database, so I changed it to "orders_restaurant" and I still have the same problem
model
package com.api.order_control.models;
import jakarta.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.UUID;
#Entity
#Table(name = "restaurant_orders")
public class OrderModel implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID id;
#Column(nullable = false, length = 11)
private String customerName;
#Column(nullable = false, length = 15)
private String phoneNumber;
#Column(nullable = false, length = 25)
private String address;
#Column(nullable = false, length = 10)
private String doorNumber;
#Column(nullable = true, length = 5)
private String block;
#Column(nullable = false, length = 30)
private String order;
#Column(nullable = false)
private Float price;
#Column(nullable = false)
private LocalDateTime registrationDate;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getDoorNumber() {
return doorNumber;
}
public void setDoorNumber(String doorNumber) {
this.doorNumber = doorNumber;
}
public String getBlock() {
return block;
}
public void setBlock(String block) {
this.block = block;
}
public String getOrder() {
return order;
}
public void setOrder(String order) {
this.order = order;
}
public Float getPrice() {
return price;
}
public void setPrice(Float price) {
this.price = price;
}
public LocalDateTime getRegistrationDate() {
return registrationDate;
}
public void setRegistrationDate(LocalDateTime registrationDate) {
this.registrationDate = registrationDate;
}
}
controller
package com.api.order_control.controllers;
import com.api.order_control.dtos.OrderDto;
import com.api.order_control.models.OrderModel;
import com.api.order_control.services.OrderService;
import jakarta.validation.Valid;
import org.springframework.beans.BeanUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.time.ZoneId;
#RestController
#CrossOrigin(origins = "*", maxAge = 3600)
#RequestMapping("/order")
public class OrderController {
final OrderService orderService;
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
#PostMapping
public ResponseEntity<Object> saveOrder(#RequestBody #Valid OrderDto orderDto) {
var orderModel = new OrderModel();
BeanUtils.copyProperties(orderDto, orderModel);
orderModel.setRegistrationDate(LocalDateTime.now(ZoneId.of("UTC")));
orderModel.setPrice(70.8f);
return ResponseEntity.status(HttpStatus.CREATED).body(orderService.save(orderModel));
}
}
Stack trace says that you have a problem in generated sql script at pos. 169. order is a keyword in sql, don't use it as a property name. Meanwhile, your table can have name orders without any problem

Java Spring Null Pointer Exception when saving ManyToOne

Trying to save an object of type "Salary" which has ManyToOne relationships with "Role", "City", "SalarySite". It appears to be printing correctly with all the expected data but saving fails. Other similar questions all seem to be missing "#Autowired" but it is present in mine.
The "Dataloader" class, runs a "GoogleSearchScraper" class where we see the error.
City
package fyi.incomeoutcome.salarytaxspend.city;
import fyi.incomeoutcome.salarytaxspend.salary.Salary;
import javax.persistence.*;
import java.util.Set;
#Entity
public class City {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String name;
private String country;
private String currency;
#OneToMany(mappedBy="city", cascade = CascadeType.ALL)
private Set<Salary> salaries;
protected City(){}
public City(String name, String country, String currency){
this.name = name;
this.country = country;
this.currency = currency;
}
public String getName(){ return this.name; }
public String getCountry(){ return this.country; }
public String toString(){
return String.format("City[id=%d, name='%s', country = '%s', currency= '%s']",
id, name, country, currency);
}
}
City Repository
package fyi.incomeoutcome.salarytaxspend.city;
import org.springframework.stereotype.Repository;
import org.springframework.data.repository.CrudRepository;
#Repository
public interface CityRepository extends CrudRepository<City, Long> {
}
Role
package fyi.incomeoutcome.salarytaxspend.role;
import fyi.incomeoutcome.salarytaxspend.salary.Salary;
import javax.persistence.*;
import java.util.Set;
#Entity
public class Role {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String seniority;
private String roleName;
#OneToMany(mappedBy="role", cascade = CascadeType.ALL)
private Set<Salary> salaries;
protected Role(){}
public Role(String seniority,String roleName){
this.seniority = seniority;
this.roleName = roleName;
}
public String getSeniorityAndRole(){
if (this.seniority != ""){
return String.format("%s %s", this.seniority, this.roleName);
} else{
return roleName;
}
}
public String toString(){
return String.format("id=%d, %s %s", id, seniority, roleName);
}
}
Role Repository
package fyi.incomeoutcome.salarytaxspend.role;
import org.springframework.stereotype.Repository;
import org.springframework.data.repository.CrudRepository;
#Repository
public interface RoleRepository extends CrudRepository<Role, Long> {
}
SalarySite
package fyi.incomeoutcome.salarytaxspend.salary.salarysite;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class SalarySite {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
private String name;
private String searchUrl;
private String salaryElementClass;
protected SalarySite(){}
public SalarySite(String name, String searchUrl, String salaryElementClass){
this.name = name;
this.searchUrl = searchUrl;
this.salaryElementClass = salaryElementClass;
}
public String getName() {
return name;
}
public String toString(){
return String.format("%s %s %s", name, searchUrl, salaryElementClass);
}
public String getSearchUrl(){
return searchUrl;
}
public String getSalaryElementClass(){
return salaryElementClass;
}
}
SalarySiteRepo
package fyi.incomeoutcome.salarytaxspend.salary.salarysite;
import org.springframework.stereotype.Repository;
import org.springframework.data.repository.CrudRepository;
#Repository
public interface SalarySiteRepository extends CrudRepository<SalarySite, Long> {
}
Salary
package fyi.incomeoutcome.salarytaxspend.salary;
import fyi.incomeoutcome.salarytaxspend.city.City;
import fyi.incomeoutcome.salarytaxspend.role.Role;
import fyi.incomeoutcome.salarytaxspend.salary.salarysite.SalarySite;
import javax.persistence.*;
#Entity
public class Salary {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
private int compensation;
#ManyToOne(optional = false)
#JoinColumn(name = "role_id")
private Role role;
#ManyToOne(optional = false)
#JoinColumn(name = "city_id")
private City city;
#ManyToOne(optional = false)
#JoinColumn(name = "site_id")
private SalarySite site;
protected Salary(){}
public Salary(int compensation, Role role, City city, SalarySite site){
this.compensation = compensation;
this.role = role;
this.city = city;
this.site = site;
}
public int getCompensation(){
return this.compensation;
}
public String getCity(){
return city.getName();
}
public String getSeniorityAndRoleName(){
return role.getSeniorityAndRole();
}
public String toString(){
return String.format("Salary[id=%d, compensation=%d, city='%s', role='%s'",
id, compensation, city, role);
}
}
Salary Repository
import fyi.incomeoutcome.salarytaxspend.city.City;
import fyi.incomeoutcome.salarytaxspend.role.Role;
import fyi.incomeoutcome.salarytaxspend.salary.salarysite.SalarySite;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface SalaryRepository extends CrudRepository<Salary, Long> {
//List<Salary> findByLocation(String location);
Salary findById(long id);
boolean existsBySiteAndCityAndRole(SalarySite salarySite, City city, Role role);
}
Dataloader
package fyi.incomeoutcome.salarytaxspend.salary.service;
import fyi.incomeoutcome.salarytaxspend.city.City;
import fyi.incomeoutcome.salarytaxspend.city.CityRepository;
import fyi.incomeoutcome.salarytaxspend.role.RoleRepository;
import fyi.incomeoutcome.salarytaxspend.salary.Salary;
import fyi.incomeoutcome.salarytaxspend.salary.SalaryRepository;
import fyi.incomeoutcome.salarytaxspend.salary.salarysite.SalarySite;
import fyi.incomeoutcome.salarytaxspend.role.Role;
import fyi.incomeoutcome.salarytaxspend.salary.salarysite.SalarySiteRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
#Component
#Slf4j
public class DataLoader {
#Autowired
private SalaryRepository salaryRepository;
#Autowired
private SalarySiteRepository siteRepository;
#Autowired
private CityRepository cityRepository;
#Autowired
private RoleRepository roleRepository;
#PostConstruct
public void process() {
List<SalarySite> salarySiteList = new ArrayList<>();
siteRepository.findAll().forEach(salarySiteList::add);
List<Role> roleList = new ArrayList<>();
roleRepository.findAll().forEach(roleList::add);
List<City> cityList = new ArrayList();
cityRepository.findAll().forEach(cityList::add);
List<Salary> salaryList = new ArrayList<>();
salaryRepository.findAll().forEach(salaryList::add);
log.info("Entering Loop");
log.info("--------------------");
int numberOfSalaries = salaryList.size();
int numberOfRoles = roleList.size();
int numberOfSites = salarySiteList.size();
int numberOfCities = cityList.size();
log.info(String.format("salary list %d", numberOfSalaries));
log.info(String.format("role list %d", numberOfRoles));
log.info(String.format("site list %d", numberOfSites));
log.info(String.format("city list %d", numberOfCities));
for (SalarySite salarySite : salarySiteList){
for (City city: cityList){
for (Role role: roleList){
boolean foundSalary = salaryRepository.existsBySiteAndCityAndRole(salarySite, city, role);
if (foundSalary == true) {
log.debug("Found");
} else {
log.debug("Not Found, Scraping");
String roleTitle = role.getSeniorityAndRole();
String cityName = city.getName();
String searchUrl = salarySite.getSearchUrl();
String salaryElementClass = salarySite.getSalaryElementClass();
ScraperService siteScraper = new GoogleSearchScraper(role, city, salarySite);
siteScraper.executeScrape();
}
}
}
}
}
}
Google Search Scraper
package fyi.incomeoutcome.salarytaxspend.salary.service;
import fyi.incomeoutcome.salarytaxspend.city.City;
import fyi.incomeoutcome.salarytaxspend.role.Role;
import fyi.incomeoutcome.salarytaxspend.salary.Salary;
import fyi.incomeoutcome.salarytaxspend.salary.SalaryRepository;
import fyi.incomeoutcome.salarytaxspend.salary.salarysite.SalarySite;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
#Component
#Slf4j
public class GoogleSearchScraper implements ScraperService {
private Role role;
private City city;
private SalarySite site;
private String webPageUrl;
private int compensation;
#Autowired
SalaryRepository salaryRepo;
public GoogleSearchScraper(){}
public GoogleSearchScraper(Role role, City city, SalarySite site){
this.role = role;
this.city = city;
this.site = site;
}
#Override
public void executeScrape(){
int statusCodeFetchUrl = fetchWebpageUrl();
log.info(String.format("fetchWebPageUrl for %s : %d", toString(), statusCodeFetchUrl));
int parsePageStatusCode = parsePageForSalary();
log.info(String.format("parseUrl for salary %s : %d", toString(), parsePageStatusCode));
saveSalary();
}
#Override
public int fetchWebpageUrl(){
String title = role.getSeniorityAndRole();
title = title.replace(" ", "+");
String searchUrl = site.getSearchUrl();
String cityName = city.getName();;
String fullUrl = String.format("%s%s+%s", searchUrl, title, cityName);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(fullUrl))
.GET()
.build();
int statusCode = 0;
try{
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
statusCode = response.statusCode();
String jsonResultLink = new JSONObject(response.body())
.getJSONArray("items")
.getJSONObject(0)
.getString("link");
log.info(city + " " + role + " " + jsonResultLink);
this.webPageUrl = jsonResultLink;
return statusCode;
} catch(Exception e) {
log.error(e.toString());
return statusCode;
}
}
#Override
public int parsePageForSalary() {
HttpClient client = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.ALWAYS)
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(this.webPageUrl))
.GET()
.build();
int statusCode = 0;
try{
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
statusCode = response.statusCode();
Document doc = Jsoup.parse(response.body());
Element salaryElement = doc.getElementsByClass(site.getSalaryElementClass()).first();
String salaryText = salaryElement.text();
char[] salaryChars = salaryText.toCharArray();
String nonDigitCharacters = "";
for (char c: salaryChars){
if (!Character.isDigit(c)){
salaryText = salaryText.replace(Character.toString(c),"");
nonDigitCharacters += c;
}
}
log.info(this.toString() + " removed " + nonDigitCharacters + " from salary " + salaryText);
this.compensation = Integer.parseInt(salaryText);
return statusCode;
} catch (Exception e){
log.error(e.toString());
return statusCode;
}
}
public void saveSalary(){
Salary scrapedSalary = new Salary(this.compensation, this.role, this.city, this.site);
log.info("saving " + scrapedSalary.toString());
salaryRepo.save(scrapedSalary);
}
#Override
public String getWebPageUrl() {
return webPageUrl;
}
#Override
public int getSalary() {
if (this.compensation == 0){
parsePageForSalary();
return this.compensation;
}
return this.compensation;
}
public String toString(){
return String.format("Scraper %s, %s, %s", role.getSeniorityAndRole(),
city.getName(), site.getName());
}
}
Error
2022-01-23 10:53:54.194 INFO 34291 --- [ main] f.i.s.s.service.GoogleSearchScraper : saving Salary[id=0, compensation=36149, city='City[id=1, name='Dublin', country = 'Ireland', currency= 'EUR']', role='id=1, Junior Software Developer'
2022-01-23 10:53:54.194 WARN 34291 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataLoader': Invocation of init method failed; nested exception is java.lang.NullPointerException
2022-01-23 10:53:54.195 INFO 34291 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-01-23 10:53:54.196 INFO 34291 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2022-01-23 10:53:54.210 INFO 34291 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
2022-01-23 10:53:54.211 INFO 34291 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2022-01-23 10:53:54.222 INFO 34291 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-01-23 10:53:54.237 ERROR 34291 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataLoader': Invocation of init method failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:160) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:440) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:620) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:953) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.14.jar:5.3.14]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.14.jar:5.3.14]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.2.jar:2.6.2]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) ~[spring-boot-2.6.2.jar:2.6.2]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) ~[spring-boot-2.6.2.jar:2.6.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) ~[spring-boot-2.6.2.jar:2.6.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.2.jar:2.6.2]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) ~[spring-boot-2.6.2.jar:2.6.2]
at fyi.incomeoutcome.salarytaxspend.SalaryTaxSpendApplication.main(SalaryTaxSpendApplication.java:27) ~[classes/:na]
Caused by: java.lang.NullPointerException: null
at fyi.incomeoutcome.salarytaxspend.salary.service.GoogleSearchScraper.saveSalary(GoogleSearchScraper.java:119) ~[classes/:na]
at fyi.incomeoutcome.salarytaxspend.salary.service.GoogleSearchScraper.executeScrape(GoogleSearchScraper.java:48) ~[classes/:na]
at fyi.incomeoutcome.salarytaxspend.salary.service.DataLoader.process(DataLoader.java:78) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:389) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:333) ~[spring-beans-5.3.14.jar:5.3.14]
at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:157) ~[spring-beans-5.3.14.jar:5.3.14]
... 18 common frames omitted
Since you are creating an instance of GoogleSearchScraper yourself, fields will not be autowired by Spring. Therefore, salaryRepository is null.
You could inject the SalaryRepository instance yourself upon creation of GoogleSearchScraper like this:
ScraperService siteScraper = new GoogleSearchScraper(role, city, salarySite, salaryRepo);
siteScraper.executeScrape();
Of course you need to add SalaryRepository to the constructor parameter list and assign it.
Consider removing #Component from GoogleSearchScraper if you want to create instances yourself. You only need it when instances shall be managed by Spring.

Exception: org.hibernate.AnnotationException: No identifier specified for entity: jpa.tenants.DataSourceConfig

I folloowing below link to understand
“https://medium.com/swlh/multi-tenancy-implementation-using-spring-boot-hibernate-6a8e3ecb251a” tutorial
package jpa.tenants;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import org.hibernate.engine.jdbc.connections.spi.AbstractDataSourceBasedMultiTenantConnectionProviderImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
#SuppressWarnings("serial")
#Component
public class DataSourceBasedMultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl {
#Autowired
private DataSource defaultDS;
#Autowired
private ApplicationContext context;
private Map<String, DataSource> map = new HashMap<>();
boolean init = false;
private String DEFAULT_TENANT_ID="1";
#PostConstruct
public void load() {
map.put(DEFAULT_TENANT_ID, defaultDS);
}
#Override
protected DataSource selectAnyDataSource() {
return map.get(DEFAULT_TENANT_ID);
}
#Override
protected DataSource selectDataSource(String tenantIdentifier) {
if (!init) {
init = true;
TenantDataSource tenantDataSource = context.getBean(TenantDataSource.class);
map.putAll(tenantDataSource.getAll());
}
return map.get(tenantIdentifier) != null ? map.get(tenantIdentifier) : map.get(DEFAULT_TENANT_ID);
}
}
Resulting into below exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path
resource [jpa/tenants/HibernateConfig.class]: Invocation of init
method failed; nested exception is org.hibernate.AnnotationException:
No identifier specified for entity: jpa.tenants.DataSourceConfig
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796)
~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)
~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108)
~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868)
~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
at jpa.JpaExample.main(JpaExample.java:10) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_232]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
~[na:1.8.0_232]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
~[na:1.8.0_232]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_232]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
[spring-boot-devtools-2.2.2.RELEASE.jar:2.2.2.RELEASE]
Caused by: org.hibernate.AnnotationException: No identifier specified for entity: jpa.tenants.DataSourceConfig
at org.hibernate.cfg.InheritanceState.determineDefaultAccessType(InheritanceState.java:266)
~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.cfg.InheritanceState.getElementsToProcess(InheritanceState.java:211)
~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:781)
~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:254)
~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:230)
~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:273)
~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1202)
~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1233)
~[hibernate-core-5.4.9.Final.jar:5.4.9.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58)
~[spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
~[spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391)
~[spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:378)
~[spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
~[spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855)
~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792)
~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
... 21 common frames omitted
'This is my DataSourceConfig Class:-'
package jpa.tenants;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import org.hibernate.annotations.Table;
import org.springframework.data.annotation.Id;
import com.fasterxml.jackson.annotation.JsonIgnore;
#Entity
#Table(appliesTo= "DATASOURCECONFIG")
public class DataSourceConfig {
#Id
#JsonIgnore
#Column(name="id", nullable=false)
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private String url;
private String username;
private String password;
private String driverClassName;
private boolean initialize;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public boolean isInitialize() {
return initialize;
}
public void setInitialize(boolean initialize) {
this.initialize = initialize;
}
}
----------------------------------------
----------
' Any help is highly appriciated thanks..'
The Id annotation in the class DataSourceConfig is imported from the wrong package:
import org.springframework.data.annotation.Id;
This must be
import javax.persistence.Id;

Error creating bean with name 'loginRepository': Invocation of init method failed; nested exception [duplicate]

This question already has answers here:
Autowiring fails: Not an managed Type
(13 answers)
Closed 4 years ago.
Here is my code:
springboot class
package com.angularjs.app.controller;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.web.bind.annotation.RestController;
//#RestController
//#EnableAutoConfiguration
#SpringBootApplication
public class Application extends SpringBootServletInitializer{
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Controller
package com.angularjs.app.controller;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import com.angularjs.app.message.Response;
import com.angularjs.app.model.LoginVO;
import com.angularjs.app.repo.LoginRepository;
//#Configuration
//#ComponentScan
//#EnableAutoConfiguration
#RestController
#EnableJpaRepositories("com.angularjs.app.repo")
public class LoginController {
//#Autowired
LoginRepository loginRepository;
#RequestMapping("/findbyusername")
public Response findByLastName(#RequestParam("username") String username) {
LoginVO userDetails = loginRepository.findByUsername(username);
return new Response("Done", userDetails);
}
#RequestMapping("/")
ModelAndView home(ModelAndView modelAndView) {
modelAndView.setViewName("home");
return modelAndView;
}
#RequestMapping(value = "/postuserdetails", method = RequestMethod.POST)
public void postCustomer(#RequestBody LoginVO loginVo) {
loginRepository.save(new LoginVO(loginVo.getUsername(), loginVo.getPassword(), loginVo.getEmail(),"Y"));
}
}
response class
package com.angularjs.app.message;
public class Response {
private String status;
private Object data;
public Response() {
}
public Response(String status, Object data) {
this.status = status;
this.data = data;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
model class
package com.angularjs.app.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "user_details")
public class LoginVO implements Serializable{
private static final long serialVersionUID = -3009157732242241606L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column (name="user_id")
private long userId;
#Column (name="user_name")
private String username;
#Column (name="valid_user")
private String validUser;
#Column (name="password")
private String password;
#Column (name="email")
private String email;
public LoginVO(String username, String password, String email, String validuser) {
this.username = username;
this.password = password;
this.email = email;
this.validUser = validuser;
}
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getValidUser() {
return validUser;
}
public void setValidUser(String validUser) {
this.validUser = validUser;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public String toString() {
return String.format("Customer[userId=%d, username='%s', email='%s']", userId, username, email);
}
}
repo class
package com.angularjs.app.repo;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Service;
import com.angularjs.app.model.LoginVO;
#Service
public interface LoginRepository extends CrudRepository<LoginVO, Long> {
LoginVO findByUsername(String userName);
}
Exception
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2018-08-25 16:23:47.591 ERROR 2702 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class com.angularjs.app.model.LoginVO
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1699) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:740) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:398) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1258) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at com.angularjs.app.controller.Application.main(Application.java:21) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_91]
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:496) [spring-boot-maven-plugin-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_91]
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.angularjs.app.model.LoginVO
at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:473) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:72) ~[spring-data-jpa-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66) ~[spring-data-jpa-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:169) ~[spring-data-jpa-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:107) ~[spring-data-jpa-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:90) ~[spring-data-jpa-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:298) ~[spring-data-commons-2.0.9.RELEASE.jar:2.0.9.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$3(RepositoryFactoryBeanSupport.java:286) ~[spring-data-commons-2.0.9.RELEASE.jar:2.0.9.RELEASE]
at org.springframework.data.util.Lazy.getNullable(Lazy.java:141) ~[spring-data-commons-2.0.9.RELEASE.jar:2.0.9.RELEASE]
at org.springframework.data.util.Lazy.get(Lazy.java:63) ~[spring-data-commons-2.0.9.RELEASE.jar:2.0.9.RELEASE]
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:289) ~[spring-data-commons-2.0.9.RELEASE.jar:2.0.9.RELEASE]
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:102) ~[spring-data-jpa-2.0.3.RELEASE.jar:2.0.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1758) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1695) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE]
... 22 common frames omitted
By adding #EntityScan(basePackageClasses=LoginVO.class) on Application class, my issue got resolved.

org.hibernate.PersistentObjectException: detached entity passed to persist domain object

I'm fairly new to Spring and I've been using this tutorial to help me build #ManyToMany relationships. I'm trying to make a ManyToMany relationship between User and Role and then another ManyToMany relationship between Role and Permission. I've followed the article throughout and I seem to be getting this error and cannot figure out why it's happening.
Note: I am using Gradle, not Maven; I don't know if that makes any difference. I am also using perisistence with org.springframework.data.repository.CrudRepository.
Stacktrace
2016-06-23 11:35:17.312 ERROR 7389 --- [ main] o.s.boot.SpringApplication : Application startup failed
java.lang.IllegalStateException: Failed to execute ApplicationRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:701)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:688)
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:678)
Exception in thread "main" at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:343)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:273)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:971)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:960)
at AdeyTrack.AdeyTrackApplication.main(AdeyTrackApplication.java:30)
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: AdeyTrack.domain.Permissions; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: AdeyTrack.domain.Permissions
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:276)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:221)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:121)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy85.save(Unknown Source)
at AdeyTrack.AdeyTrackApplication.createRoleIfNotFound(AdeyTrackApplication.java:112)
at AdeyTrack.AdeyTrackApplication.run(AdeyTrackApplication.java:76)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:698)
... 7 common frames omitted
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: AdeyTrack.domain.Permissions
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:801)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:794)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:97)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:379)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:319)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:296)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:470)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:295)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:195)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:291)
at com.sun.proxy.$Proxy78.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:439)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:452)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:437)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:409)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
java.lang.IllegalStateException: Failed to execute ApplicationRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:701)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:688)
at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:678)
at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:343)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:273)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:971)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:960)
at AdeyTrack.AdeyTrackApplication.main(AdeyTrackApplication.java:30)
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: AdeyTrack.domain.Permissions; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: AdeyTrack.domain.Permissions
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:276)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:221)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:121)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy85.save(Unknown Source)
at AdeyTrack.AdeyTrackApplication.createRoleIfNotFound(AdeyTrackApplication.java:112)
at AdeyTrack.AdeyTrackApplication.run(AdeyTrackApplication.java:76)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:698)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
... 7 more at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 17 common frames omitted
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: AdeyTrack.domain.Permissions
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:801)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:794)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:97)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:379)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:319)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:296)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:470)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:295)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:195)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:291)
at com.sun.proxy.$Proxy78.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:439)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:452)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:437)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:409)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 17 more
ApplicationRunner:
package AdeyTrack;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import AdeyTrack.domain.Role;
import AdeyTrack.domain.Permissions;
import AdeyTrack.domain.User;
import AdeyTrack.persistence.repository.PermissionsRepository;
import AdeyTrack.persistence.repository.RoleRepository;
import AdeyTrack.persistence.repository.UserRepository;
#SpringBootApplication
public class AdeyTrackApplication implements ApplicationRunner {
boolean setup = false;
public static void main(String[] args) {
SpringApplication.run(AdeyTrackApplication.class, args);
}
#Autowired
private UserRepository userRepo;
#Autowired
private PermissionsRepository permRepo;
#Autowired
private RoleRepository roleRepo;
#Override
public void run(ApplicationArguments args) throws Exception {
BCryptPasswordEncoder pe = new BCryptPasswordEncoder();
if(setup){ return ; }
/* Create permissions */
Permissions edit_store = createPermissionsIfNotFound(Permission.STORE.PERM_STORE_EDIT.name(), "edit a store");
Permissions create_store = createPermissionsIfNotFound(Permission.STORE.PERM_STORE_CREATE.name(), "create a store");
List<Permissions> adminPermissions = Arrays.asList(edit_store, create_store);
/* Create roles */
createRoleIfNotFound("STORE_ADMIN", adminPermissions);
createRoleIfNotFound("STORE_EDITOR", Arrays.asList(create_store));
Role adminRole = roleRepo.findByRole("STORE_ADMIN");
Role editRole = roleRepo.findByRole("STORE_EDITOR");
User storeadmin = new User("storeadmin", pe.encode("password"));
User storeedit = new User("storeedit", pe.encode("password"));
storeadmin.setRoles(Arrays.asList(adminRole));
storeedit.setRoles(Arrays.asList(editRole));
userRepo.save(storeadmin);
// userRepo.save(storeedit);
setup = true;
}
#Transactional
private Permissions createPermissionsIfNotFound(String name, String description){
Permissions permission = permRepo.findByPermission(name);
if(permission == null){
permission = new Permissions(name, description);
permRepo.save(permission);
}
return permission;
}
#Transactional
private Role createRoleIfNotFound(String name, Collection<Permissions> permissions) {
Role role = roleRepo.findByRole(name);
if (role == null) {
role = new Role(name);
role.setPermissions(permissions);
roleRepo.save(role);
}
return role;
}
}
User.java
package AdeyTrack.domain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name="users")
public class User {
#Id
#GeneratedValue
private Integer id;
private String login;
private String password;
private boolean enabled;
#ManyToMany(cascade = {CascadeType.ALL})
#JoinTable(name="users_roles",
joinColumns = {#JoinColumn(name="user_id", referencedColumnName="id")},
inverseJoinColumns = {#JoinColumn(name="role_id", referencedColumnName="id")}
)
private Collection<Role> roles = new ArrayList<>();
public User(){
super();
}
public User(String login, String password){
super();
this.login = login;
this.password = password;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Collection<Role> getRoles() {
return roles;
}
public void setRoles(Collection<Role> role) {
this.roles = role;
}
public void setRole(Role role) {
this.roles.add(role);
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
Role.java
package AdeyTrack.domain;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
#Entity
#Table(name="roles")
public class Role {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String role;
#ManyToMany(mappedBy = "roles")
private Collection<User> users;
#ManyToMany(cascade = {CascadeType.ALL})
#JoinTable(name="role_permissions",
joinColumns = {#JoinColumn(name="role_id", referencedColumnName="id")},
inverseJoinColumns = {#JoinColumn(name="permission_id", referencedColumnName="id")}
)
private Collection<Permissions> rolePermissions;
public Role(){
super();
}
public Role(String role){
super();
this.role = role;
}
public Role(String role, Collection<Permissions> permissions){
super();
this.role = role;
this.rolePermissions = permissions;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public void setUsers(Collection<User> users){
if(users.size() == 1){
this.users = users;
} else if(users.size() > 1){
this.users.addAll(users);
}
}
public Collection<User> getUsers(){
return users;
}
public void setPermissions(Collection<Permissions> permissions){
this.rolePermissions = permissions;
}
public Collection<Permissions> getPermissions(){
return rolePermissions;
}
}
Permission.java
package AdeyTrack.domain;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name="permissions")
public class Permissions {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#ManyToMany(mappedBy = "rolePermissions", cascade = CascadeType.ALL)
private Collection<Role> roles;
private String permission;
private String description;
public Permissions(){
super();
}
public Permissions(String permission, String description){
super();
this.permission = permission;
this.description = description;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Collection<Role> getRole() {
return roles;
}
public void setRole(Collection<Role> role) {
this.roles = role;
}
public String getPermission(){
return permission;
}
public void setPermission(String permission){
this.permission = permission;
}
public String getDescription(){
return description;
}
public void setDescription(String description){
this.description = description;
}
}
Any help would be appreciated.
By using #Transactional, many important aspects such as transaction propagation are handled automatically. In this case if another transactional method is called by businessLogic(), that method will have the option of joining the ongoing transaction.
#Transactional
public void businessLogic() {
... use entity manager inside a transaction ...
}
One potential downside is that this powerful mechanism hides what is going on under the hood, making it hard to debug when things don't work.
One of the key points about #Transactional is that there are two separate concepts to consider, each with it's own scope and life cycle:
the persistence context
the database transaction
The transactional annotation itself defines the scope of a single database transaction. The database transaction happens inside the scope of a persistence context.
The persistence context is in JPA the EntityManager, implemented internally using an Hibernate Session (when using Hibernate as the persistence provider).
The persistence context is just a synchronizer object that tracks the state of a limited set of Java objects and makes sure that changes on those objects are eventually persisted back into the database.
This is a very different notion than the one of a database transaction. One Entity Manager can be used across several database transactions, and it actually often is.
So I feel extremely stupid because the whole issue lies in the Application runner. After doing a little bit more digging around I discovered that it is vital to use #Transactional in the run method, I have no clue why this is the case but just adding that annotation has fixed everything for some reason.

Categories

Resources