0

I need to do a "CRUD" with a table, but the table in the database doesn't have a primary key, so I then changed @Entity to @Embeddable. I now have this problem with my @repository.

@Embeddable
@Table(name = "TB_MAIN")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class TB_Main {

@Column(name = "EXPOSURE")
private String exposureType;

@Column(name = "TIPOLOGY")
private String tipology;
}

@Repository
public interface TbMainRepository extends CrudRepository<TB_Main,String>{

}

@Service
public class ManualLoadImpl implements ManualLoadService {
    //Repository
    @Autowired
    private TbMainRepository tbMainRepo;

The code err is:

11-03-2020 10:48:05.928 [main] ERROR o.s.boot.SpringApplication.reportFailure - Application run failed
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'manualLoadImpl': Unsatisfied dependency expressed through field 'tbMainRepo'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tbMainRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class posicion.app.model.manualload.TB_Main
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:598)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:376)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1404)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:847)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1204)
    at posicion.app.Application.main(Application.java:10)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'tbMainRepository': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Not a managed type: class posicion.app.model.manualload.TB_Main
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1771)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:593)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1255)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1175)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:595)
    ... 19 common frames omitted
Caused by: java.lang.IllegalArgumentException: Not a managed type: class posicion.app.model.manualload.TB_Main
    at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:552)
    at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:74)
    at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:201)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:151)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:134)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:65)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:305)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$5(RepositoryFactoryBeanSupport.java:297)
    at org.springframework.data.util.Lazy.getNullable(Lazy.java:211)
    at org.springframework.data.util.Lazy.get(Lazy.java:94)
    at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:300)
    at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:121)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1830)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1767)
    ... 29 common frames omitted

How can I fix this?

Draken
  • 3,134
  • 13
  • 34
  • 54
EduBw
  • 866
  • 5
  • 20
  • 40
  • 1
    `@Embeddable` is meant to embed information to their owning entities, but not meant to act as an entity itself. – Glains Mar 11 '20 at 10:05
  • 1
    No id at all? In that case you can barely know how to update a specific row in the database (kinda defating the purpose of CRUD). Is it possible that both fields together are the composite id of that table? – Joachim Sauer Mar 11 '20 at 10:05
  • [This question may help](https://stackoverflow.com/questions/3820897/jpa-entity-without-id) – Draken Mar 11 '20 at 10:06

6 Answers6

3

It's not possible to have Entities without a primary key and Embeddables can only live inside an Entity.

You have to create the primary key in the Entity using columns from your table that form a unique key.

Draken
  • 3,134
  • 13
  • 34
  • 54
Simon Martinelli
  • 34,053
  • 5
  • 48
  • 82
1

You are correct to use @Entity to signal this as a table. You need to use the @Id on one field to indicate that this is the primary key within your table. Every table should have one. @Embeddable is for another purpose. For example, see below.

@Id
@Column(name = "EXPOSURE")
private String exposureType;
Coder
  • 197
  • 1
  • 17
1
  1. The best solution is to add the primary key to your table.
  2. Your can add @Id annotation to all the fields in your class. But use this workaround carefully, because it can be applied only when your are going to read data, in case of insert hibernate will generate update SQL statement if there are the same entry in the database.
D. Krauchanka
  • 264
  • 3
  • 15
1

@Embeddable annotation is used to declare that the class will be embedded by another entity. Check for @EmbeddedId : I referred hibernate docs Hiberate 3.5 annotations reference

Nouli
  • 211
  • 1
  • 3
1

It's not just Spring-data-JPA - a relational data model require primary keys. So what you've got is a broken data model because without a primary key it can't be relational, and this is why it is difficult to use with an ORM. You can fix this by defining a surrogate key.

Shivam Patil
  • 48
  • 10
1

you had better take out this annotation

@Table(name = "TB_MAIN")

I used before similar class. you can look at my github reporsitory https://github.com/celalaygar/Spring-Boot-2/tree/master/Spring-Boot-13-SpringData-3-JPA-Hibernate-PostgreSQL/src/main/java/com/example/demo/entity

@Embeddable
public class CarDetails {
    @Column(name="details")
    private String Details;
}

@Entity
@Table(name = "car")
public class Car {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "name")
    private String name;

    @Column(name = "model")
    private int model;

    private CarDetails car_details;

    public Car() {
    }

    public Car(String name, int model) {
        super();
        this.name = name;
        this.model = model;
    }

    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 int getModel() {
        return model;
    }

    public void setModel(int model) {
        this.model = model;
    }
    @Embedded
    public CarDetails getCar_details() {
        return car_details;
    }

    public void setCar_details(CarDetails car_details) {
        this.car_details = car_details;
    }

}