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;
................
Related
I am using a view in my entity class. Although the view-column mappings are exactly the same as in entity class, I am receiving the exception "ERROR: relation "location_view" does not exist - Position: 15 - underlying exception is SQLGrammarException could not extract ResultSet at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:261)"
When I replace the view to the underlying SQL query, it works in SpringBoot. Can you please let me know where I am going wrong?
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
#Data
#ToString
#Entity
#Table(name = "location_view")
public class Location{
#Id
#Column(name = "id")
long id;
#Column(name = "name")
String name;
#Column(name = "total")
long total;
#Column(name = "created_by")
long createdBy;
#Column(name = "created_on")
Timestamp createdOn;
}
public interface LocationDAO extends JpaRepository<Location, Long> {
#Query(value = "select * from location_view", nativeQuery = true)
List<Location> getLocations();
}
In my controller, I am making call to locationDAO.getLocations();
Probably the table/view is in a different schema? Or maybe the user for the JDBC connection has no permission to read from that table/view?
Here's my Reader :
private static final String SELECT_ALL_BOOKS = "SELECT * FROM BOOKS WHERE COLOR = 'yellow'";
#Bean
public JdbcCursorItemReader<BookEntity> itemReader(final DataSource dataSource) {
return new JdbcCursorItemReaderBuilder<BookEntity>()
.name("book_reader")
.sql(SELECT_ALL_BOOKS)
.dataSource(dataSource)
.rowMapper(new BeanPropertyRowMapper<>(BookEntity.class))
.build();
}
And my entity :
#Entity
#Getter
#Setter
#Table(name = "book")
#AllArgsConstructor
#NoArgsConstructor
public class BookEntity implements java.io.Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id_book")
private Integer idBook;
#Column(name = "color")
private String color;
#Column(name = "page_number")
private Integer pageNumber;
#Column(name = "read")
private Boolean read;
#ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
#JoinColumn(name = "id_author")
private Author author;
...
...
}
Problem is : with my job executing my step, I'm having the books but with an author = null. So the foreign key is not mapped correctly, all the other String/Integer/Boolean fields are retrieved correctly.
I'm new with Spring batch so maybe I'm using a wrong kind of reader.
Any one has an idea about the problem ? Thanks
Please refer this- You are using JDBC Item reader that is mapped to native columns and properties are binded by BeanPropertyRowMapper
https://docs.spring.io/spring-batch/docs/current/reference/html/readersAndWriters.html#JdbcCursorItemReader
Change the query join with AUTHOR tables as a native query or use JPA readers to support ORM
Below reference will give repository reader
https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/item/data/RepositoryItemReader.html
Below example give some idea to implement and its SO references
https://github.com/gpassini/Spring-Batch-RepositoryItemReader-NativeQuery-Example/tree/master/src/main
I have an entity class below. As an important that, user_config column keeps JSON based user configuration so that I had to annotate the variable with #Lob.
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "user_name")
#NotNull
private String userName;
#Lob
#Column(name = "user_config")
#NotNull
private String userConfig;
I am trying to get a bunch of entries over the JPA repository from the database below:
#Repository
public interface UserConfigRepository extends CrudRepository<UserConfig, Long> {
List<UserConfig> findByUserName(String userName);
}
Finally, I have an exception below:
Caused by: org.postgresql.util.PSQLException: Bad value for type long : "some user info"
at org.postgresql.jdbc.PgResultSet.toLong(PgResultSet.java:2894)
at org.postgresql.jdbc.PgResultSet.getLong(PgResultSet.java:2101)
at org.postgresql.jdbc.PgResultSet.getClob(PgResultSet.java:447)
at org.postgresql.jdbc.PgResultSet.getClob(PgResultSet.java:434)
at com.zaxxer.hikari.pool.HikariProxyResultSet.getClob(HikariProxyResultSet.java)
at org.hibernate.type.descriptor.sql.ClobTypeDescriptor$1.doExtract(ClobTypeDescriptor.java:44)
at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:257)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253)
at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:243)
at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:329)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:3087)
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1877)
at org.hibernate.loader.Loader.hydrateEntityState(Loader.java:1805)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1778)
at org.hibernate.loader.Loader.getRow(Loader.java:1626)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:743)
at org.hibernate.loader.Loader.getRowsFromResultSet(Loader.java:1042)
at org.hibernate.loader.Loader.processResultSet(Loader.java:993)
at org.hibernate.loader.Loader.doQuery(Loader.java:962)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:352)
at org.hibernate.loader.Loader.doList(Loader.java:2857)
... 102 more
Could you please assist me to fix this error?
PS:SpringBoot Version:2.3.2.RELEASE
In spring boot JPA I tried to implement sequence generator but it is not working.
the following is my entity
#Entity
#Table(name = "role_level")
public class RoleLevel implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
#Id
#SequenceGenerator(name = "role_level_sequence", sequenceName = "role_level_id_seq",allocationSize = 1)
#GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "role_level_sequence")
#Column(name = "id", updatable = false)
private Long id;
#Column(name = "role_level")
private String roleLevel;
#Column(name = "role_level_description")
private String roleLevelDescription;
//getters and setters
}
when I insert value in directly through the database then next sequence from the db is not getting in jpa.it shows
org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "role_level_pkey"
Detail: Key (id)=(7) already exists.
But the console shows
Hibernate: select nextval ('role_level_id_seq')
I think its not working.
Is there any solution for this.?
I have these two entities:
Anagrafica
#Entity
#Access(AccessType.FIELD)
#Table(name = "S_MC_CC_USER")
#SequenceGenerator(name = "SEQ_ID", sequenceName = "SEQ_ID", allocationSize = 1)
public class Anagrafica implements Serializable{
private static final long serialVersionUID = 332466838544720886L;
#EmbeddedId
private AnagraficaId anagraficaId;
#Column(name = "USER_ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_ID")
private Long userId;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "USER_ID", updatable = false, insertable = false)
private List<Mobile> mobiles;
/**
* La classe di dominio che modella la chiave primaria di un {#link Anagrafica}
*
* #author Massimo Ugues
*
*/
#Embeddable
static public class AnagraficaId implements Serializable {
private static final long serialVersionUID = -54640203292300521L;
#Column(name = "ANAG_UTENTE")
private String bt;
#Column(name = "COD_ABI")
private String abi;
public AnagraficaId() {
super();
}
Mobile
#Entity
#Table(name = "S_MOBILE")
#SequenceGenerator(name = "SEQ_MOBILE", sequenceName = "SEQ_MOBILE", allocationSize = 1)
public class Mobile implements Serializable{
private static final long serialVersionUID = 5999493664911497370L;
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_MOBILE_DEVICE_REGISTRY")
#Column(name = "ID_MOBILE")
private Long mobileId;
#Column(name = "DEVICE_TOKEN")
private String deviceToken;
#Column(name = "DATA_INSERIMENTO")
#Temporal(TemporalType.TIMESTAMP)
private Calendar dataInserimento = Calendar.getInstance();
With eclispe-link 2.1.2 all works great, but with eclispe-link 2.5.1 I got this exception:
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.EntityManagerSetupException
Exception Description: Predeployment of PersistenceUnit [persistence-unit] failed.
Internal Exception: Exception [EclipseLink-7220] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The #JoinColumns on the annotated element [field mobiles] from the entity class [class com.intesasanpaolo.domain.entities.sub.Anagrafica] is incomplete. When the source entity class uses a composite primary key, a #JoinColumn must be specified for each join column using the #JoinColumns. Both the name and the referencedColumnName elements must be specified in each such #JoinColumn.
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.createPredeployFailedPersistenceException(EntityManagerSetupImpl.java:1954)
at org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.predeploy(EntityManagerSetupImpl.java:1945)
at org.eclipse.persistence.jpa.PersistenceProvider.createContainerEntityManagerFactory(PersistenceProvider.java:322)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:288)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1571)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1509)
... 40 more
The problem is the OneToMany association based on a foreign key that is not primary key.
Since I cannot change the database model how can I make it work?
Kind regards
Massimo
The reason it worked in a prior version was that it EclipseLink doesn't look at the fields in the mapping, but with JPA adding derived Id support, EclipseLink now validates the number of foreign keys match the number of ID fields.
James' answer here
JPA #JoinColumn issues while joining on non primary key columns
explains it that you'll need to use a descriptorCustomizer to change the JPA mapping. So you would either not map the field in JPA (mark it as #Transient) and then add a mapping in the customizer, or have the JPA mapping to use all primary key fields and then change the mapping in the customizer to only use the USER_ID->USER_ID fields.
EclipseLink customizers are shown here:
http://eclipse.org/eclipselink/documentation/2.4/jpa/extensions/a_customizer.htm
Ok, this is the Customizer I created:
public void customize(ClassDescriptor descriptor) throws Exception {
// handle the oneToManyMapping to non foreign keys
ManyToManyMapping mapping = (ManyToManyMapping) descriptor.getMappingForAttributeName("mobileDevices");
ExpressionBuilder builder = new ExpressionBuilder();
mapping.setSelectionCriteria(builder.getField("USER_ID").equal(builder.getParameter("USER_ID")));
// handle the insert statement
mapping.setInsertCall(new SQLCall(""));
}
As suggested from Chris this works great with the selection.
I had to modify the Insert Call since eclipse-link tried to create and insert statement on a mapping table that I haven't.
The problem now is on the delete: when I try to delete the collection from the source association (i.e. Cliente) as described here
Cliente.ClienteId id = new Cliente.ClienteId(abi, bt);
Cliente cliente = clienteRepository.findOne(id);
cliente.setMobileDevices(null);
I need eclipse link to delete the orphan.
The dml generated is the following:
DELETE FROM S_MC_CC_CLIENTI_S_MOBILE_DEVICE_REGISTRY WHERE ((mobileDevices_ID_MOBILE_DEVICE_REGISTRY = 13) AND ((ANAG_UTENTE = '71576493') AND (COD_ABI = '01025')))
Since I haven't the mapping table I modified the customizer adding a setDeleteCall statement :
mapping.setDeleteCall(new SQLCall("DELETE FROM S_MOBILE_DEVICE_REGISTRY WHERE USER_ID = #USER_ID"));
In this way eclipse link generates 2 dml:
DELETE FROM S_MOBILE_DEVICE_REGISTRY WHERE USER_ID = NULL
DELETE FROM S_MOBILE_DEVICE_REGISTRY WHERE (ID_MOBILE_DEVICE_REGISTRY = 13)
The first is the translation of my SQLCall, but without the correct parameter: any idea how to generate only the correct delete statement?
Kind regards.
Massimo