Entity not being loaded, or Mysterious "No property 'saveAll' found..." or "Could not safely identify store assignment..." - spring

I want JPA to recognize an entity, and generate the SQL necessary to create the table. I can get it to fail in one of the following ways. Below I show the error, followed by the code for the entity. The behavior changed depending on which package was used for things like Table so I deliberately showed which one was being used below.
Error: RepositoryConfigurationExtensionSupport : Spring Data JDBC - Could not safely identify store assignment for repository candidate interface com.woodsman.jpatutorial.orders.repositories.OrderHeaderRepository; If you want this repository to be a JDBC repository, consider annotating your entities with one of these annotations: org.springframework.data.relational.core.mapping.Table.
OrderHeader.java:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
#Entity This should be simple, but I think there's several pack
#Builder
#Data
#NoArgsConstructor
#AllArgsConstructor This should be simple, but I think there's several pack
#EqualsAndHashCode
#Table(name = "order_header")
public class OrderHeader {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private String id; -->
private String customerName;
}
Error: Error creating bean with name 'orderHeaderRepository' defined in com.woodsman.jpatutorial.orders.repositories.OrderHeaderRepository defined in #EnableJdbcRepositories declared on JdbcRepositoriesRegistrar.EnableJdbcRepositoriesConfiguration: Could not create query for public abstract java.util.List org.springframework.data.jpa.repository.JpaRepository.saveAllAndFlush(java.lang.Iterable); Reason: No property 'saveAll' found for type 'OrderHeader'
OrderHeaderRepository.java:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.woodsman.jpatutorial.orders.entities.OrderHeader;
#Repository
public interface OrderHeaderRepository extends JpaRepository<OrderHeader,Long>{
}
OrderHeader.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
#Entity
#Builder
#Data
#NoArgsConstructor
#AllArgsConstructor
#EqualsAndHashCode
#org.springframework.data.relational.core.mapping.Table(name = "order_header",schema = "orders")
public class OrderHeader {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
private String customerName;
}
application-h2.properties
spring.datasource.url=jdbc:h2:mem:ordersdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL;DATABASE_TO_LOWER=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE
spring.datasource.username=ordersadmin
spring.datasource.password=secret
spring.jpa.database=mysql
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create-drop
database, ALWAYS initialize the database
spring.sql.init.mode=ALWAYS
spring.flyway.user=ordersadmin
spring.flyway.password=secret
spring.flyway.locations=db/migration,db/specific/h2
spring.flyway.defaultSchema=orders
application.properties:
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.type.descriptor.sql=trace
spring.h2.console.enabled=true
spring.jpa.show-sql=true
spring.data.jdbc.reposi -->
tories.enabled=true
Update: Switched back to Spring Boot 2.7.3 and things work. Using Spring Boot version 3.0.0+ apparently removes the EnableJpaRepositories annotation. Without that annotation, and with the 3.0.0+ Spring Boot version, Spring said the entity wasn't a managed type. Per #M.Deinum's comment, I commented out spring-boot-starter-data-jdbc and the code did run, but it wouldn't actually generate the create sql.
I'm convinced that this should work in the 3.0.0-M5 Spring Boot, albeit with somewhat substantial changes to dependencies, and perhaps new annotations being added, so I'm not considering my question answered. Also, I made the entity id type Long to be consistent with the repository.

Related

springbroot 404 when using multi-modei

I want set two different tables.i have try this first model with corresponding service,controller and respository.Everythings is fine but when i use the same code with only changing the model,and develop a set of service,controller and respository.It cannot show what i expected.
my model:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SecondaryTable;
import javax.persistence.Table;
#Data
#AllArgsConstructor
#NoArgsConstructor
#javax.persistence.Entity
#Table(schema = "order")
public class Order {
#Id
#GeneratedValue
private int id;
private String product_name;
private int quantity;}
mycontroller:
package com.javatechie.trymysql.contoller;
import com.javatechie.trymysql.Entity.Order;
import com.javatechie.trymysql.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
#RestController
public class OrderController {
#Autowired
private OrderService service;
#PostMapping("/add/orders")
public List<Order> addOrders(#RequestBody List<Order> orders){
return service.saveOrders(orders);
}
}
service:
package com.javatechie.trymysql.service;
import com.javatechie.trymysql.Entity.Order;
import com.javatechie.trymysql.repository.OrderRepository;
import com.javatechie.trymysql.repository.ProductRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
#Service
public class OrderService {
#Autowired
private OrderRepository Repository;
public List<Order> saveOrders(List<Order> order) {
return Repository.saveAll(order);
}
}
repository:
package com.javatechie.trymysql.repository;
import com.javatechie.trymysql.Entity.Order;
import com.javatechie.trymysql.Entity.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface OrderRepository extends JpaRepository<Order,Integer> {
}
my ide pattern is like:
com.javatechie.trymysql
-entity
--Product
--Order
-controller
--productcontroller
--ordercontroller
-service
--productservice
--orderservice
-repository
--productrespository
--orderreposiory
-productconfig
-Trymysqlapplication
Postman request:
[{
"proudct_name":"sand",
"quantity":5
},{
"product_name":"fruit",
"quantity":2
}]
error:
{
"timestamp": "2022-10-17T13:14:03.284+00:00",
"status": 500,
"error": "Internal Server Error",
"path": "/add/orders"
}
Everytime i run the server it display the following log:
Hibernate: select product0_.id as id1_1_0_, product0_.name as name2_1_0_, product0_.price as price3_1_0_, product0_.quantity as quantity4_1_0_ from product_tbl product0_ where product0_.id=?
Hibernate: select product0_.id as id1_1_0_, product0_.name as name2_1_0_, product0_.price as price3_1_0_, product0_.quantity as quantity4_1_0_ from product_tbl product0_ where product0_.id=?
But it still works fine
later i add the second table it just show me:
Hibernate: select order0_.id as id1_0_0_, order0_.product_name as product_2_0_0_, order0_.quantity as quantity3_0_0_ from order order0_ where order0_.id=?
2022-10-17 21:21:11.916 WARN 3828 --- [nio-9191-exec-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1064, SQLState: 42000
i dont why my log file automatically generate this sql and got the error when it is not the model "product"?
I dont know which step i have done wrong when trying using the second model(order)
Extracted details from comments.
As you have table name order which is a reserved keyword in MySQL. So you have to change the table name to another name that is not a reserved keyword. Change to orders resolves the issue.

JPA not creating tables it found at startup

I'm new to JPA and am working through examples on a UDemy course and got confused with the various Spring initialization on startup options. My entity is not being created on application startup, though as an H2 in-memory database it should because it's not there.
My application-h2.properties:
spring.datasource.url=jdbc:h2:mem:ordersdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL;DATABASE_TO_LOWER=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE
spring.datasource.username=ordersadmin
spring.datasource.password=secret
spring.jpa.database=mysql
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=create-drop
#spring.datasource.defer-datasource-initialization=FALSE
#spring.jpa.defer-datasource-initialization=false
spring.sql.init.mode=NEVER
spring.flyway.user=ordersadmin
spring.flyway.password=secret
spring.flyway.locations=db/migration,db/specific/h2
spring.flyway.defaultSchema=orders
My application.properties:
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.type.descriptor.sql=trace
spring.h2.console.enabled=true
My entity class:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Builder;
import lombok.Data;
#Entity
#Builder
#Data
public class OrderHeader {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;
private String customerName;
}
Ultimately, I'm trying to get the SQL for the table put into a Flyway configuration file, but prefer to start with JPA's generated SQL statement for this. I thought telling it
spring.jpa.hibernate.ddl-auto=create-drop would tell it to create or drop any tables it needed to, but it's not doing that.
My confusion comes from properties like:
spring.sql.init.mode
spring.datasource.defer-datasource-initialization
I believe these were related to non-Flyway/non-Liquibase type initialization driven by some schema.sql file, but can't find consistent docs on that.

Lombok annotation Value. Cannot find method 'value'

#Repository
#AllArgsConstructor
public class DataProvider {
#Value("${db.url}")
private String dbUrl;
}
IDE - idea
Plugin installed in IDE,dependecy installed
import # value from import org.springframework.beans.factory.annotation.Value;
it works
1- verifier your import, maybe you imported value from lombok, and it's wrong,so change your import:
import lombok.Value;
to:
import org.springframework.beans.factory.annotation.Value;

MongoRepository Delete Method

Good afternoon fellow coders!
I have spent the last hour looking to delete a single document from my mongo "testCollection". I would like to make use of the MongoRepository delete / deleteAll methods. However, it does not remove the document. It persists regardless of how many times I run the test class method. No errors are reported and the user has readWrite permissions in the database. I am able to run the mongo command to remove the newly created test document.
I have read about using the mongo template and create it for the deletion to be performed. I'm happy to do that but I would rather keep it as simple as possible.
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoId;
#Data
#Document(collection = "testCollection")
public class TestClass {
#MongoId
private String id;
private String name;
public TestClass(String name) {
this.name = name;
}
}
Test Class Mongo Repository interface
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;
public interface TestClassRepository extends MongoRepository<TestClass, String> {
public List<TestClass> findAllByName(String name);
public void deleteAllByIdIn(List<TestClass> list);
}
Test Method
import org.junit.Assert;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
#RunWith(SpringRunner.class)
#TestPropertySource(value = {"classpath:application.properties"})
#AutoConfigureMockMvc
public class testClassTest {
#Autowired
private TestClassRepository testClassRepository;
#Test
public void crudTest() {
TestClass testObj = new TestClass("Test");
testClassRepository.save(testObj);
List<TestClass> testClassList = testClassRepository.findAllByName("Test");
Assert.assertEquals(1, testClassList.size());
TestClass test = testClassList.get(0);
testClassRepository.deleteAllByIdIn(testClassList);
// Fails this assertion: Found 1, expected 0.
Assert.assertEquals(0, testClassRepository.findAllByName("Test").size());
}
}
As anyone else experienced a similar issue? If so, how'd you go about resolving it?
Thanks!
Additions to original post:
Here is the mongo query generated by the MongoRepository. It appears that it is not actually adding the "remove" mongo command to the query. Query: { "name" : "Test"}, Fields: {}, Sort: {}
With a stroke of dumb luck I managed to figure out the issue. The problem was with the type of identifier annotation I was using. This explanation from another stackoverflow user (What is use of #MongoId in Spring Data MongoDB over #Id?) had me revisit this aspect of the model.
I switched the identifier annotation from #MongoId to #Id. Since I have both JPA and MongoDB annotations I needed to make sure I chose the one from the org.springframework.data.annotation package rather than the javax.persistance package.
Hope this explanation helps others!

In Spring boot application is #Component annotation optional for repo

I have created the basic application using Spring boot using JPA. I have added #AutoWired annotation for RatingRepo in RatingResource, but haven't added #Component annotation to RatingRepo
package com.example.demo;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.RatingsRateService.model.Rating;
import com.example.demo.RatingsRateService.model.UserRating;
#RestController
#RequestMapping("ratingsdata")
public class RatingResource {
#Autowired
RatingRepo repo;
/*
* #RequestMapping("/{movieId}") public Rating
* getRating(#PathVariable("movieId") String movieId) { return new
* Rating(movieId,7); }
*/
#RequestMapping("users/{userid}")
public UserRating getRating(#PathVariable("userid") int userid) {
List<Rating> ratings =repo.findByUserId(userid);
/*
* List<Rating> ratings = Arrays.asList(new Rating("1",4), new Rating("2",3),
* new Rating("3",2));
*/
System.out.println(ratings);
UserRating userRating = new UserRating();
userRating.setUserRating(ratings);
return userRating;
}
}
package com.example.demo;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import com.example.demo.RatingsRateService.model.Rating;
//to update the data in database , created the interd=face and will implement
//class,primary key
public interface RatingRepo extends JpaRepository<Rating, Integer>{
#Query(" from Rating where userid = ?1")
List<Rating> findByUserId( int userid);
}
. Still, it is working fine. Can you someone please explain why it is so? Or it is not needed to add #Component annotation for the repo?
first of there is #Repository annotation required not #Component
and #Repository also auto configure due to below:
Probably you are using spring boot
Spring Data repositories usually extend from the Repository or CrudRepository interfaces. If you are using auto-configuration, repositories will be searched from the package containing your main configuration class (the one annotated with #EnableAutoConfiguration or #SpringBootApplication) down.
ref: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-spring-data-jpa-repositories

Resources