The CrudRepository bean
#Repository
public interface UserDao extends CrudRepository<User, Long>
{
List<User> findByFirstNameAndLastName(String firstName, String lastName);
}
for the User resource
#Entity
#Table(name="User")
public class User
{
#Id
#GeneratedValue
private long id;
#Column(name="first_name")
private String firstName;
#Column(name="last_name")
private String lastName;
/* --- Getters,setters,default constructor -------*/
}
is not created when I start my Spring boot app
Field dao in base.package.service.UserService required a bean
of type 'base.package.dao.UserDao' that could not be found.
but the packages are definitely scanned
#SpringBootApplication(scanBasePackages= {"base.package"})
I got the strong suspicion that it has to do something with the embedded database h2 that I am using. I am trying to create the User table in schema.sql
CREATE TABLE IF NOT EXISTS User (
id INTEGER NOT NULL AUTO_INCREMENT,
first_name VARCHAR(128) NOT NULL,
last_name VARCHAR(128) NOT NULL,
PRIMARY KEY (id)
);
but as soon as I uncomment IF NOT EXISTS it throws an error (table already exists). So this firstly means that spring takes charge of created the schema. But I get the feeling that the table is not recreated because in the data.sql script
INSERT INTO User (id,first_name,last_name) VALUES (1,'Vincent', 'Vega');
I always have to manually increment the id on startup otherwise i get a
org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.USER(ID)"
Here are the jpa properties from application.properties
# below properties create schema, so schema.sql is redundant
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create-drop
spring.datasource.initialization-mode=always
spring.jpa.database=H2
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.show-sql=true
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.url=jdbc:h2:~/testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE
spring.datasource.name=testdb
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
The reason why I think that the table is never recreated on startup is because I get this error when the app closes
2018-02-02 09:27:47.907 INFO [restartedMain] [StandardService] Stopping service [Tomcat]
2018-02-02 09:27:47.907 WARN [localhost-startStop-1] [WebappClassLoaderBase] The web application [ROOT] appears to have started a thread named [MVStore background writer nio:C:/Users/user/testdb.mv.db] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
This is followed by the exception that UserDao bean is not created.
***************************
APPLICATION FAILED TO START
***************************
Description:
Field dao in base.package.user.service.UserService required a bean of type 'base.package.user.dao.UserDao' that could not be found.
Action:
Consider defining a bean of type 'base.package.user.dao.UserDao' in your configuration.
POM.XML
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.M7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.M5</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
/* .... */
EDIT
Here is the UserService
#Service
public class UserService
{
#Autowired private UserDao dao;
public List<User> findByFirstNameAndLastName(String firstName, String lastName)
{
return dao.findByFirstNameAndLastName(firstName, lastName);
}
public User save(final User user)
{
return dao.save(user);
}
}
EDIT 2
Now I am getting
Caused by: java.lang.IllegalArgumentException: Not a managed type: class com.project.bot.user.User
at org.hibernate.metamodel.internal.MetamodelImpl.managedType(MetamodelImpl.java:472)
at org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation.<init>(JpaMetamodelEntityInformation.java:72)
at org.springframework.data.jpa.repository.support.JpaEntityInformationSupport.getEntityInformation(JpaEntityInformationSupport.java:66)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getEntityInformation(JpaRepositoryFactory.java:169)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:107)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactory.getTargetRepository(JpaRepositoryFactory.java:90)
at org.springframework.data.repository.core.support.RepositoryFactorySupport.getRepository(RepositoryFactorySupport.java:300)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.lambda$afterPropertiesSet$3(RepositoryFactoryBeanSupport.java:287)
at org.springframework.data.util.Lazy.getNullable(Lazy.java:141)
at org.springframework.data.util.Lazy.get(Lazy.java:63)
at org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport.afterPropertiesSet(RepositoryFactoryBeanSupport.java:290)
at org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean.afterPropertiesSet(JpaRepositoryFactoryBean.java:102)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1769)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1706)
... 102 common frames omitted
The table not being created should not have any impact on whether the bean is defined or not.
I think the problem you have here is that you are not instatiating your repository beans. Spring Data JPA repository beans are not picked up by component scans since they are only interfaces. The #Repository annotation actually does nothing here.
Spring Data JPA repo beans are created dynamically provided you have supplied the #EnableJpaRepositories in your configuration.
You may also need to put an #EntityScan to make sure all your #Entity's are recognised by Spring
#SpringBootApplication(scanBasePackages= {"base.package"})
#EnableJpaRepositories("base.package")
#EntityScan("base.package")
Related
I should probably mention that Spring is my first framework that I am learning for Java.
What I am trying to do is to get the JDBC working for me using the Spring Data JDBC dependency I downloaded from spring.io. (2.6.4) I followed a tutorial on YouTube where the guy demonstrated it with something similar to the following code. (Should also mention the code he used was for Spring version 2.2 but I'm not sure where else to find right code for 2.6.4)
There is also an UnsatisfiedDependencyException I keep getting where it says:
Error creating bean with name 'applicationRunner' defined in com.example.demo.DemoApplication: Unsatisfied dependency expressed through method 'applicationRunner' parameter 0;
I do not know why this is happening. But here is the actual code:
package com.example.demo;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
ApplicationRunner applicationRunner(StudentRepo studentRepo) {
return args -> {
var s1 = Student.createStudent("John", "Doe");
var s2 = Student.createStudent("Jane", "Doe");
System.out.println(studentRepo.save(s1));
System.out.println(studentRepo.save(s2));
System.out.println(studentRepo.findByFName("John"));
};
}
}
CRUD Repository interface:
import org.springframework.data.jdbc.repository.query.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface StudentRepo extends CrudRepository<Student, String> {
#Query("SELECT * FROM Students WHERE name = :name")
List<Student> findByFName(#Param("name") String fName);
}
schema.sql file:
CREATE TABLE Students (
id VARCHAR(50) IDENTITY PRIMARY KEY,
firstName VARCHAR(50),
lastName VARCHAR(50),
rank VARCHAR(50)
);
I think it's also important for me to include pom.xml file: (Though it should also be mentioned that the pom.xml file didn't originally include the hsqldb dependency. I added that in myself.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Edit:
Exception after including #Repository in the CRUD repository interface:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'applicationRunner' defined in com.example.demo.DemoApplication: Unsatisfied dependency expressed through method 'applicationRunner' parameter 0
Exception after replacing #Repository with #NoRepositoryBean:
2022-03-23 18:30:06.531 INFO 98567 --- [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2022-03-23 18:30:06.556 ERROR 98567 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
APPLICATION FAILED TO START
Description:
Parameter 0 of method applicationRunner in com.example.demo.DemoApplication required a bean of type 'com.example.demo.StudentRepo' that could not be found.
Action:
Consider defining a bean of type 'com.example.demo.StudentRepo' in your configuration.
Process finished with exit code 1
try modifying the bean:
#Bean
public CommandLineRunner demo(StudentRepo studentRepo) {
return (args) -> {
studentRepo.save(new Student("Jack", "Bauer"));
studentRepo.save(new Student("Chloe", "O'Brian"));
}
you can consult the guide https://spring.io/guides/gs/accessing-data-jpa/
The problem lies in the schema.sql script. An IDENTITY column in HSQLDB has to be of the type INTEGER or BIGINT (see documentation at http://www.hsqldb.org/doc/1.8/guide/ch09.html, section CREATE TABLE). All other errors are just subsequent errors.
I am working on a Spring Boot application trying to use Spring Data JPA and Hibernate but I am finding some difficulties trying to insert a new record into an example table.
This is my application pom.xml file content:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.easydefi</groupId>
<artifactId>GET-USER-WS</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>GET-USER-WS</name>
<description>Microservice that retrieves users from DB</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
This is my application.properties file content:
spring.datasource.url = jdbc:postgresql://172.21.0.2:5432/EasyDefiDB
spring.datasource.username = postgres
spring.datasource.password = MY_PSWD
spring.datasource.driver-class-name = org.postgresql.Driver
spring.jpa.hibernate.ddl-auto = none
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
Then into my Postgres I created a DB named EasyDefiDB containing this very simple Example table that I am using to perform some experiment:
CREATE TABLE IF NOT EXISTS public."Example"
(
id bigint NOT NULL,
test character varying(50) COLLATE pg_catalog."default" NOT NULL,
CONSTRAINT "Example_pkey" PRIMARY KEY (id)
)
So I created this Example entity class:
package com.easydefi.users.entity;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
#Entity
#Table(name = "Example")
#Data
public class Example implements Serializable {
private static final long serialVersionUID = -2878723722630662986L;
#Id
#Column(name = "id")
private int id;
#Column(name = "test")
private String test;
public Example(String test) {
super();
this.test = test;
}
public Example() {
super();
}
}
Then I created this ExampleRepository extenting JpaRepository interface:
public interface ExampleRepository extends JpaRepository<Example, Integer> {
}
At the moment this interface is empty because I am only trying to save a new record using the JpaRepository save() method.
Finnally I created this unit test class in order to test the saving behavior:
#SpringBootTest()
#ContextConfiguration(classes = GetUserWsApplication.class)
#TestMethodOrder(OrderAnnotation.class)
public class ExampleRepositoryTest {
#Autowired
private ExampleRepository exampleRepository;
#Test
#Order(1)
public void TestInsertExample()
{
Example example = new Example("TEST");
exampleRepository.save(example);
assertTrue(true);
}
}
The problem is that running this method, when the save() method is called it give me the following error in my stacktrace:
2021-11-03 17:10:59.059 INFO 15054 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
2021-11-03 17:10:59.416 WARN 15054 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning
2021-11-03 17:11:00.453 INFO 15054 --- [ main] c.e.users.GetUserWsApplicationTests : Started GetUserWsApplicationTests in 5.067 seconds (JVM running for 6.686)
2021-11-03 17:11:00.812 INFO 15054 --- [ main] o.s.t.c.support.AbstractContextLoader : Could not detect default resource locations for test class [com.easydefi.users.tests.RepositoryTests.ExampleRepositoryTest]: no resource found for suffixes {-context.xml, Context.groovy}.
2021-11-03 17:11:00.818 INFO 15054 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.event.ApplicationEventsTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener]
2021-11-03 17:11:00.818 INFO 15054 --- [ main] .b.t.c.SpringBootTestContextBootstrapper : Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener#703eead0, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener#674fd531, org.springframework.test.context.event.ApplicationEventsTestExecutionListener#7f53b345, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener#76ee7301, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener#71817f66, org.springframework.test.context.support.DirtiesContextTestExecutionListener#68feca3a, org.springframework.test.context.transaction.TransactionalTestExecutionListener#ad585fb, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener#fa689db, org.springframework.test.context.event.EventPublishingTestExecutionListener#75a6bd06, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener#6b170692, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener#4d4bac56, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener#76980c75, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener#3696d12d, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener#656672fb, org.springframework.boot.test.autoconfigure.webservices.client.MockWebServiceServerTestExecutionListener#75df4b1d]
Hibernate:
insert
into
example
(test, id)
values
(?, ?)
2021-11-03 17:11:09.867 WARN 15054 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 42P01
2021-11-03 17:11:09.869 ERROR 15054 --- [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: relation "example" does not exist
Position: 13
So basically the problem seems that, for some reason that I cannot uderstand, it is trying to insert into the example table and not into the Example (as it is defined in my DB, with the first uppercase char).
Renaming my table from Example to example it works fine, the new record is correctly inserted into this table.
But why? How can I change this behaviour allowing me to correctly insert into a table starting with an uppercase letter?
So according to the graphql-java-kickstart/graphql-java-tools a 'graphql' endpoint should become available when the dependency 'com.graphql-java-kickstart:graphql-spring-boot-starter' is added to the project and .graphqls schema files are scanned automatically.
I have the following dependencies:
...
<spring-boot.version>2.3.3.RELEASE</spring-boot.version>
<graphql.version>7.0.1</graphql.version>
<graphql-java-tools.version>6.2.0</graphql-java-tools.version>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- graphql -->
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>${graphql.version}</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>${graphql.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>${graphql-java-tools.version}</version>
</dependency>
A schema definition:
in query.graphqls:
type Query {
user(username: String!)
users: [User]
}
in user.graphqls:
type User {
userId: Number!
username: String!
}
And a GraphQLQueryResolver for that:
#Component
public class UserQueryResolver implements GraphQLQueryResolver {
private final UserRepository userRepository;
public UserQueryResolver(UserRepository userRepository) {
this.userRepository = userRepository;
}
public Iterable<User> users() {
return this.userRepository.findAll();
}
public User user(String username) {
return this.userRepository.findByUsername(username).orElseThrow();
}
}
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByUsername(String username);
}
According to the documentation:
The servlet becomes accessible at /graphql if graphql-spring-boot-starter added as a dependency to a boot application and a GraphQLSchema bean is present in the application. Check out the simple example for the bare minimum required.
A GraphQL schema can also be automatically created when a supported graphql-java schema library is found on the classpath.
The graphql-java-tools library should automatically create a schema, under these conditions:
All GraphQLResolver and GraphQLScalar beans, along with a bean of type SchemaParserDictionary (to provide all other classes), will be used to create a GraphQLSchema. Any files on the classpath named *.graphqls will be used to provide the schema definition. See the Readme for more info.
I think I have everything it needs, but navigating to localhost:8080/graphql gives a 404.
N.B.: localhost:8080/graphiql works, but it cannot load the schema. It says:
{
"timestamp": "2020-09-15T12:22:21.748+00:00",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/graphql"
}
What am I missing?
Apparently the application could not find any JpaRepositories, because the SpringBootApplication starter class was located in com.package.some.app while the repositories were in com.package.some.domain.repositories. The Component scanner was only scanning components with package com.package.som.app.*
I have created a SpringBoot multi module project.
You can find the basic projectstructure here.
Now I'm trying to generate tables using Hibernate in the model-module.
Prerequisites:
database in docker environment:
docker run --name postgres -e POSTGRES_PASSWORD=user -e POSTGRES_USER=user -e POSTGRES_DB=postgres -p 5432:5432 -d postgres
model/pom.xml:
<project ...>
...
<dependencies>
<!--general-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--persistence-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
</dependencies>
</project>
model/src/main/resources/application-model.properties:
# spring datasource
spring.database.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=user
spring.datasource.password=user
# hibernate
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto = update
model/src/main/java/model/ModelConfig.java:
...
#SpringBootApplication
#EntityScan("com.test.model.*")
#PropertySource("classpath:application-model.properties")
public class ModelConfig {
}
model/src/main/java/model/MyEntity.java:
...
#Entity
#Data
public class MyEntity {
#Id
#GeneratedValue
private long id;
#Column
private String text;
}
web/src/main/java/web/WebConfig.java:
...
#Configuration
#ComponentScan("com.test.*")
public class WebConfig {
}
WebConfig is a configurationclass which right next to the WebApplication.java which has the main-function of the application.
So the #ComponentScan("com.test.*") in WebConfig should scan in com.test.model as well and find the ModelConfig bean, which in fact is the case:
taken from Intellij
In ModelConfig the annotation #EntityScan("com.test.model.*") should search for entities in com.test.model.*, which is the case for MyEntity.java.
Error:
Actually there is no error, #mvn clean install runs and builds everything and I can run the application without getting any error messages as you can see in the output.
But there is no table generated.
Expectations:
I expect this setup to generate a table called <my_entity>, with a id-field with autogeneration and a field called text with varchar(255), which are the defaults of #GeneratedValue and #Column in MyEntity.java.
Thanks in advance.
I'm trying to setup a simple Database with an article which may contains comments with Spring Data JPA. However as soon as I enable the comment relation on the article Hibernate throws an exception:
o.h.t.s.i.ExceptionHandlerLoggedImpl : GenerationTarget encountered exception accepting command : Error executing DDL via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
[...]
Caused by: java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: PUBLIC.ARTICLE_COMMENTS
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) ~[hsqldb-2.4.1.jar:2.4.1]
at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) ~[hsqldb-2.4.1.jar:2.4.1]
at org.hsqldb.jdbc.JDBCStatement.fetchResult(Unknown Source) ~[hsqldb-2.4.1.jar:2.4.1]
at org.hsqldb.jdbc.JDBCStatement.execute(Unknown Source) ~[hsqldb-2.4.1.jar:2.4.1]
at com.zaxxer.hikari.pool.ProxyStatement.execute(ProxyStatement.java:95) ~[HikariCP-2.7.9.jar:na]
at com.zaxxer.hikari.pool.HikariProxyStatement.execute(HikariProxyStatement.java) ~[HikariCP-2.7.9.jar:na]
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:54) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
... 157 common frames omitted
My article class looks as follows:
#Entity
public class Article {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
private String abstractText;
private String author;
private Date createdAt;
private int visibility;
private int likes;
private int views;
private int commentCount;
#OneToMany(cascade=CascadeType.ALL)
private List<Comment> comments;
// getters and setters omitted
}
And the Comment:
#Entity
public class Comment {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String commentText;
private Date createdAt;
}
And the pom contains dependencies to HSQLDB, PostgreSQL, Spring Boot Starter Data JPA and Spring Boot Starter Web:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
When I remove the relation to the Comment List, it works. Any suggestions?
Seems like the spring.jpa.hibernate.ddl-auto property were the problem. Spring defaults it to create-drop for in-memory databases. However, in the current Spring Boot or HSQLDB or Hibernate version (or maybe the combination?) this seems to cause problems. After changing the value to update, it just works fine.
The exception you saw is just a WARNING, and it really doesn't mean anything broken. If you use show-sql: true options, you will see this warning is actually cause by alter table comment DROP CONSTRAINT XXXXX, which is part of Hibernate creation DDL, and hsqldb doesn't have any table when this query executed.
Changing to ddl-auto: update has its side-effect. import.sql won't work with this option.
To avoid this WARNING, you could add these lines to your application.yaml:
logging:
level:
org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl: ERROR
The issue for me was in dependency I provided.
I have a column #Column(nullable = false, columnDefinition = "text") and old dependency doesn't support this column definition. That's why I had to change
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<scope>test</scope>
</dependency>
to this
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>