JPA failed to automatically generate a table from an entity - jpa

I am using Eclipselink with Derby database to automatically generated a database from Entities.
The generation worked just fine at first, but when i added a User entity to my model and tried to generate tables from entities with JPA tools all the tables are generated except the User table & i get the following error during the generation
[EL Warning]: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.1.v20150605-31e8258): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: Syntax error: Encountered "USER" at line 1, column 14.
Error Code: 30000
This is the user entity
#NamedQuery( name = "User.findByUsername", query = "SELECT u FROM User u WHERE u.username = :userneme AND u.password = :password" )
#Entity
public class User implements Serializable {
#Transient
private static final long serialVersionUID = 1L;
public User() {
super();
}
#Id
#GeneratedValue( strategy = GenerationType.AUTO )
private Integer id;
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername( String username ) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword( String password ) {
this.password = password;
}
Can anyone tell me why i am getting the exception ?
Thanks in advance

Your table name is "USER" which is a reserved keyword in SQL (and in Apache Derby). Some JPA providers (e.g DataNucleus JPA) automatically quote such keywords for you meaning it would just work. Others (e.g EclipseLink) don't and so you have to explicitly set the table name with surrounding quote marks (') or set the table name to something that is not a SQL keyword
#Table(name="'User'")
public class User {...}

This most likely is because USER is a function in the Derby Database (Refer this : http://db.apache.org/derby/docs/10.10/ref/rrefsqlj42476.html). You possibly can have the JPA bean as User , but specify a different table name using #Table annotation

Related

Custom query in spring boot JPA using postgres db

I am connecting my spring boot application to postgres db, i am able insert values using JPA. Now i want to retrieve data from the table. I would like to use the #Query from JPA to select the column in the table. while i run the application i get sql error. Here is the repository code
#Query(value = "SELECT user.firstname AS firstName, user.lastName AS lastName FROM user_details user WHERE emailid LIKE ?1", nativeQuery = true)
EmailOnly findUserByEmail(String emailId);
public static interface EmailOnly {
String getFirstName();
String getLastName();
}
Entity class
#Getter
#Setter
#Entity
#Table(name = "USER_DETAILS")
public class UserDetails {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private int userId;
private String emailId;
private String firstName;
private String lastName;
}
I get error as
SQL Error: 0, SQLState: 42601 2020-03-23 17:04:05.128 ERROR 27508 ---
[nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR:
syntax error at or near "."
All the example in jpa shows to select data using aliases, but its now working for me. If i try to remove all the aliases from the query i am getting the projection values as null.

Hibernate #Column annotation cannot mapping to database

I have a Entity in Spring Boot and PostgreSql, I'm using #Column annotation to mapping to database. This is my Entity snip code :
#Entity(name = "users")
#Table(name = "users", schema = "public")
public class User implements Serializable {
/**
*
*/
private static final long serialVersionUID = 12355345L;
#Id
#Column(name = "user_id")
private String userid;
#Column(name = "user_name")
private Integer username;
When id run and test with postman, i get an error :
org.springframework.dao.InvalidDataAccessResourceUsageException: could
not extract ResultSet; SQL [n/a]; nested exception is
org.hibernate.exception.SQLGrammarException: could not extract
ResultSet
Caused by: org.postgresql.util.PSQLException: ERROR: column users0_.usersid does not exist
Hint: Perhaps you meant to reference the column "users0_.user_id".
I don't know why. How to resolve this ?
There are couple of things for your info.
1) Need to check your spring.jpa.hibernate.ddl-auto property as depends on that property, the database tables, columns will be populated by Hibernate.
2) Next drop the existing table and change the value as spring.jpa.hibernate.hbm2ddl.auto=update so that it will create/update table according to the annotations provided in the entity class
3) Remove unnecessary annotations. Following is enough.
#Entity
#Table(name = "users")
public class User implements Serializable {
#Id
#Column(name = "user_id")
private String userid;
................

Schema-validation: missing table [game]

I think it may be possible dupplicate of this: Schema-validation: missing table [hibernate_sequences] but I can't figure it out.
So in my application.properties file I have this option: spring.jpa.hibernate.ddl-auto=validate and I receive this error:
Schema-validation: missing table [game]
Why I am receiving this?
Here is my Game class and User class:
Game:
#Entity
public class Game {
#Id
#Column(name = "GAME_NUMBER")
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private long gameNumber;
private int playerScore;
private int NPCScore;
private Date datetime;
#ManyToOne
#JoinColumn(name="USER_ID")
private User user;
public Game() {}
public Game(int playerScore, int nPCScore, Date datetime) {
super();
this.playerScore = playerScore;
this.NPCScore = nPCScore;
this.datetime = datetime;
}
public User getUser() {
return user;
}
} + getters & setters
User:
#Entity
public class User {
#Id
#Column(name = "USER_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private long userId;
private String username;
private String password;
#OneToMany(mappedBy="user",cascade=CascadeType.ALL)
private List<Game> games;
#ElementCollection
private List<Date> startSessions;
public User() {}
public User(String username, String password, List<Game> games, List<Date> startSessions) {
super();
this.username = username;
this.password = password;
this.games = games;
this.startSessions = startSessions;
}
}
validate validates that the entities are compatible against the target, to a degree it's not foolproof. Anyway, whatever database you are trying to validate against does not have a table called game in which to store the entities.
This answer goes into more detail about what validate does.
Hibernate - hibernate.hbm2ddl.auto = validate
specifically,
checks the presence of tables, columns, id generators
Without knowing your database/expectations (are you expecting it to be created, or using Flyway/Liquibase to create/update the database etc.) I can't answer if validate is correct for your use case.
You could try create-drop to create and drop the table on startup/shutdown, but this isn't a solution for any production control over a database.
I got the same as I changed to Hibernate 5.4.0.Final.
Either Hibernate suddenly has problems to recognize the default schema or the driver does not return the schema properly.
I was able to bypass it by either adding the schema definition to the table definition.
#Table(name = "GAME", schema = "PUBLIC")
or by adding a default schema in persistence.xml.
<property name="hibernate.default_schema" value="PUBLIC" />
Don't forget permissions:
GRANT select, insert, update, delete, alter ON table_name TO usr_name;
This error can appear while using spring boot with flywayDB.
The issue might be due to the wrong naming convention of script files, which were used by flywayDB.
https://flywaydb.org/documentation/migrations#naming
The SQL standard requires names stored in uppercase.
If you named the table/fields in lowercase - JPA can automatically convert case to upper and trying to search names in this case, but write to logs in lower ¯\_(ツ)_/¯
Add this in application.yml:
spring:
jpa:
properties:
hibernate:
default_schema: game
Hibernate version 5.6.9,
Case-sensitive implementation:
hibernate:
physical_naming_strategy: 'org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl'

What's wrong with my JPQL query?

I am trying to implement join but I am facing error. I have product table and store table. product table references store table through foreign key as shown below:
Product.java
#Entity
public class Product {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long pId;
private String model;
private String brand;
private byte[] image;
private Long price;
private String currency;
private String transmissionType;
private String fuelType;
#ManyToOne
#JoinColumn(name="storeId")
private Store store;
// … getters and setters
}
Now, I show the Store.java
#Entity
public class Store {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long storeId;
private String locality;
private String city;
private String state;
private String zipCode;
private String phone;
// … getters and setters
}
Now , I show the repository
public interface ProductRepo extends JpaRepository<Product, Long> {
#Query("select p from Product p join p.storeId s where p.storeId = s.storeId and s.city = :city")
public List<Product> findByCity(#Param("city") String city);
#Query("select p from Product p join p.storeId s where p.storeId = s.storeId and s.state = :state")
public List<Product> findByState(#Param("state") String state);
}
Now, the error comes due to the last two queries where I implement join. What i want to do is get all products whose store is in particular city or state as you can see above.
The error I encounter is :
Error starting ApplicationContext. To display the auto-configuration
report re-run your application with 'debug' enabled. 2016-10-16
09:53:25.203 ERROR 16132 --- [ main]
o.s.boot.SpringApplication : Application startup failed
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'catalogueServiceController':
Unsatisfied dependency expressed through field 'productRepo'; nested
exception is org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'productRepo': Invocation of init method
failed; nested exception is java.lang.IllegalArgumentException:
Validation failed for query for method public abstract java.util.List
com.practice.rest.assignment1.repository.ProductRepo.findByCity(java.lang.String)!
and so on ....
What is the error in my query ?
The query is invalid. You refer to a p.storeId which doesn't exist. I think something like this should be sufficient:
select p from Product where p.store.city = :city
Or:
select p from Product join p.store as store where store.city = :city
The upper should be sufficient as your JPA provider should be able to do the right thing for you then. The latter might be preferred if you want to be more specific about the join type to optimize the query.
The same applies to the other query. For future reference: everything you cut off the exception stack trace would've been the interesting part 😉. If persistence providers reject JPQL, they're usually very specific about the error they encounter. So you should be able to find something around p.storeId being an invalid reference somewhere deeper down the stack trace actually.

How can I set foriegn key column in Spring JPA

I am using Spring JPA and want to set value to a foreign key column. Here is my entities and repository.
#Entity
public class Device {
#NotEmpty
#Id
private String deviceId;
#ManyToOne
#JoinColumn(name="userId", referencedColumnName="userId", insertable=false, updatable=false)
#NotFound(action=NotFoundAction.IGNORE)
private User user;
//Getters and setters
}
#Entity
public class User(){
#Id
private String userId;
private String userName;
//Getters and setters
}
public interface DeviceRepository extends PagingAndSortingRepository {
}
public class DeviceServiceImpl implements DeviceService {
#Autowired
private DeviceRepository devRepos;
#Autowired
private UserRepository userRepos;
#Override
public void saveDevice(Device device, String userId) {
User user = null;
if (userId!=null) {
user = userRepos.findOne(userid);
device.setUser(user);
}
deviceRepos.save(device);
}
}
The user exists in Device table but userId column in the table does not set the value. Please help me to fix the problem.
EDIT:
I removed insertable and updatable from the annotation and now it works.
#JoinColumn(name="userId", referencedColumnName="userId")
Then, this means I have to get user of the device from the User table whenever I save a device?
Because you set insertable and updatable to false for the user property in your Device class , it will cause the persistence provider to ignore this column (Device.userId) when generating SQL INSERT and UPDATE statement.
Just change them to true or remove them as their default values are already true.
Update :
this means I have to get user of the device from the User table
whenever I save a device?
In pure JPA , if you know the ID of the user , you can use EntityManager#getReference(User.class , aUserId) to get an User instance without actually querying from DB . But in Spring Data JPA , it seems that this method is not supported out of the box.