0

I am creating a Spring Boot application using the H2 database. I am constantly getting the following error:

Table "THINGS_TO_DO" not found; SQL statement:
insert into things_to_do (id, name, verified) values (1, 'TestUser1', 1) [42102-197]

And, I feel this is logical since I don't know where to pass this table name in the application. Also, what should the table name be - is there some specific name that the table must have?

My ThingsToDo.java is like below:

package me.hiboy.springboot.microservice.example.todo;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="things_to_do")
public class ThingsToDo {

    @Id
    private Long id;

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

    @Column(name="verified")
    private int verificationStatus;

    private String task;

    public ThingsToDo() {

    }

    public ThingsToDo(Long id, String name, int verificationStatus, String task) {
        super();
        this.id=id;
        this.name=name;
        this.verificationStatus=verificationStatus;
        this.task=task;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getVerificationStatus() {
        return verificationStatus;
    }

    public String getTask() {
        return task;
    }
}

The controller ThingsToDoController.java is as follows:

package me.hiboy.springboot.microservice.example.todo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ThingsToDoController {

    @Autowired
    ThingsToDoRepository repository;

    @GetMapping("/")
    public String index() {
        return "Hello from the ToDo Controller\n";
    }

    @GetMapping("/todo/{name}")
    public ThingsToDo getThingsToDo(@PathVariable String name) {
        ThingsToDo thingToDo=repository.findByName(name);

        return thingToDo;
    }
}

Repository ThingsToDoRepository is:

package me.hiboy.springboot.microservice.example.todo;

import org.springframework.data.jpa.repository.JpaRepository;

public interface ThingsToDoRepository extends JpaRepository<ThingsToDo, Long> {
    ThingsToDo findByName(String name);
}

Application.properties is:

spring.application.name=todo-service
server.port=8080
spring.jpa.show-sql=true
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:mydb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.platform=h2
spring.datasource.initialize=true

data.sql is:

insert into things_to_do (id, name, verified) values (1, 'TestUser1', 1);
insert into things_to_do (id, name, verified) values (2, 'TestUser2', 0);

I don't think pom.xml is required - in case it is, kindly lemme know and I will post that as well. Thanks.

Edit: The one with the main() method is here:

package me.hiboy.springboot.microservice.example.todo.springbootmicroservicetodoservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootMicroserviceTodoServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootMicroserviceTodoServiceApplication.class, args);
    }
}

Edit: All the answers given so far do not help at all.

P.K.
  • 379
  • 1
  • 4
  • 16

4 Answers4

1

Follow the package name as If your main class is in the com.example package then all packages in your application will be following this package as for new entity, the package will be com.example.entity

Anil Kumar
  • 11
  • 4
  • Sorry, are you saying my directory structure is wrong currently? – P.K. Apr 21 '18 at 18:46
  • I am saying to verify it once from your end as you are not posted your main class I am guessing it that maybe it is the reason – Anil Kumar Apr 21 '18 at 18:58
  • As i am seeing u are not following the structure – Anil Kumar Apr 21 '18 at 19:00
  • Well, [this link](https://stackoverflow.com/a/40902759/2172854) says that a structure is not required. So would I be good if I just move the main class file outside to com.example? – P.K. Apr 21 '18 at 19:14
  • Sorry, this is not helpful at all! I am following the same structure as given in the tutorial!! – P.K. Apr 21 '18 at 21:31
0

You are getting this error because there is no table with such name.

You could try to add spring.jpa.hibernate.ddl-auto=create-drop to your .properties file. Then each time you run your app it should generate that table using your entity.

Or you need to create a table with name things_to_do manually and then when you run your app it should work. For this, you need to add

/src/main/resources/schema.sql

create table things_to_do
(
   id integer not null,
   /*all the rest columns */
);

Another thing is that for Spring to find your components (like repository or service etc.) it scans packages. And auto-configs scan the package where your main class is located and all the nested packages.

So if you don't want to set manually where your classes are located, you need to follow this structure!

Example:

my.main.package // here is your main class
my.main.package.entities // here are your entities
my.main.package.repositories // your repos
my.main.package.services // services

This is just an example, it does not mean you should provide the same names, just follow the convention. Hope it is clear what I mean by package structure :)

ikos23
  • 4,879
  • 10
  • 41
  • 60
  • But I am using the H2 database. So, aren't the tables created automatically? Is my understanding incorrect? Also, I still get the same error, unfortunately. (Anyway, I had tried this before). – P.K. Apr 21 '18 at 18:35
  • I guess you need to provide spring boot main class code as well. The one with the main method. I guess you are missing some configs. Then I could update my answer. – ikos23 Apr 21 '18 at 18:38
  • I will check. I also updated my answer, you could try add `schema.sql` and check if it makes any difference. – ikos23 Apr 21 '18 at 18:46
  • Got you. Thank you. – P.K. Apr 21 '18 at 18:47
  • Well, I am following the exact same structure as given in the tutorial. – P.K. Apr 21 '18 at 21:32
0

You need to use proper package names as I can see you Application class and other classes do not follow the package naming convention.

Plus If I just want to insert simple test data I often implement a ApplicationRunner. Implementations of this interface are run at application startup and can use e.g. a autowired repository to insert some test data.

Your implementation would look like this:

@Component
public class DataLoader implements ApplicationRunner {

    @Autowired
    ThingsToDoRepository repository;

    @Autowired
    public DataLoader(ThingsToDoRepository repository) {
        this.repository = repository;
    }

    public void run(ApplicationArguments args) {
        repository.save(new ThingsToDo(1, 'TestUser1', 1));
        repository.save(new ThingsToDo(2, 'TestUser2', 0));
    }
}
UsamaAmjad
  • 4,175
  • 3
  • 28
  • 35
0

Usually, you would refer to your table by its entity name, not the actual table name. In this case it would be ThingsToDo.

But in this particular case, you're overriding this by giving your entity another name:

@Entity
@Table(name="things_to_do")
public class ThingsToDo {

That's why you should work with "things_to_do" in your query, or remove the name statement.