Reputation: 41
I am trying to set up a database (currently with 2 entities).
The first package contains the first one:
// Recipe.java
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
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.OneToMany;
import uk.ac.ic.doc.group33.nutrioapi.user.User;
@Entity
public class Recipe {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String name;
private int estimatedMins;
private String photo;
@ElementCollection
private List<String> instructions;
@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Ingredient> ingredients;
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "user",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "recipe_id", referencedColumnName = "id"))
private List<User> users;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getEstimatedMins() {
return estimatedMins;
}
public void setEstimatedMins(int estimatedMins) {
this.estimatedMins = estimatedMins;
}
public String getPhoto() {
return photo;
}
public void setPhoto(String photo) {
this.photo = photo;
}
public List<String> getInstructions() {
return instructions;
}
public void setInstructions(List<String> instructions) {
this.instructions = instructions;
}
public List<Ingredient> getIngredients() {
return ingredients;
}
public void setIngredients(List<Ingredient> ingredients) {
this.ingredients = ingredients;
}
}
// RecipeController.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class RecipeController {
@Autowired
private RecipeRepository recipeRepository;
@GetMapping("/recipes")
public Iterable<Recipe> getAllRecipes() {
return recipeRepository.findAll();
}
@PostMapping("/recipes/add")
public String addRecipe(@RequestBody Recipe recipe) {
recipeRepository.save(recipe);
return "success";
}
}
// RecipeRepository.java
import org.springframework.data.repository.CrudRepository;
public interface RecipeRepository extends CrudRepository<Recipe, Integer> {
}
And some helper classes in that package too (Ingredient and Unit, both working fine). This table is able to be created without any issues.
The other package:
// User.java
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import uk.ac.ic.doc.group33.nutrioapi.recipe.Recipe;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String email;
@ManyToMany(mappedBy = "users")
private List<Recipe> recipes;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
// UserController.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserRepository userRepository;
@GetMapping("/users")
public Iterable<User> getAllUsers() {
return userRepository.findAll();
}
@PostMapping("/users/add")
public String addRecipe(@RequestBody User user) {
userRepository.save(user);
return "success";
}
}
// UserRepository.java
import org.springframework.data.repository.CrudRepository;
public interface UserRepository extends CrudRepository<User, Integer> {
}
In the package above these, I have the main API class:
// NutrioApiApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Main application class
@SpringBootApplication
public class NutrioApiApplication {
public static void main(String[] args) {
SpringApplication.run(NutrioApiApplication.class, args);
}
}
When I added the User entity, it can create the Recipe table but not the User one. I get many errors along these lines:
GenerationTarget encountered exception accepting command : Error executing DDL "create table user (id int4 not null, email varchar(255), user_id int4 not null, recipe_id int4 not null, primary key (id))" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "create table user (id int4 not null, email varchar(255), user_id int4 not null, recipe_id int4 not null, primary key (id))" via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlString(AbstractSchemaMigrator.java:559) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.applySqlStrings(AbstractSchemaMigrator.java:504) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.createTable(AbstractSchemaMigrator.java:277) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.tool.schema.internal.GroupedSchemaMigratorImpl.performTablesMigration(GroupedSchemaMigratorImpl.java:71) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.performMigration(AbstractSchemaMigrator.java:207) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:114) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:184) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:73) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:314) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1249) ~[hibernate-core-5.4.15.Final.jar!/:5.4.15.Final]
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391) ~[spring-orm-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:830) ~[na:na]
Caused by: org.postgresql.util.PSQLException: ERROR: syntax error at or near "user"
I believe I followed the Spring guidelines for linking properly so I'm not sure why the table name is causing a syntax error.
Can anyone help?
UPDATE: I added
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
to application.properties.
Upvotes: 0
Views: 731
Reputation: 41
I found the issue was in Recipe.java, in the @JoinTable, I was still referring to the table as 'user'
Upvotes: 0
Reputation: 1090
user
is a reserved word in PostgreSQL (https://postgresql.org/docs/8.1/sql-keywords-appendix.html). This will not happen in your 'integration tests' as they probably use a test in-memory db.
Can you annotate your User
entity with something like:
@Entity
@Table(name="my_users_table")
public class User {
// ...
}
Upvotes: 2