PersistenceException from a simple CRUD for a simple class - jpa

Using the in-memory database (db=mem), I'm simply trying to insert a new object into the database using CRUD.
The class is as follows:
#Entity
public class ActivityModel extends Model {
#Required
public String description;
#Required
public String link;
#Required
public Date timestamp;
public ActivityModel(String description, String link, Date timestamp) {
this.description = description;
this.link = link;
this.timestamp = timestamp;
}
}
And the CRUD controllers looks like this:
#CRUD.For(ActivityModel.class)
public class Activities extends CRUD {
}
Yet, when I try to add a new activity to the database, I get the following error:
13:48:20,710 INFO ~ Application 'ScoreDB' is now started !
13:48:48,323 WARN ~ SQL Error: -177, SQLState: 23000
13:48:48,323 ERROR ~ Integrity constraint violation - no parent FKF0DCD93AADF686FF table: USERMODEL in statement [insert into ActivityModel (id, description, link, timestamp) values (null, ?, ?, ?)]
13:48:48,370 ERROR ~
#65pagp52g
Internal Server Error (500) for request POST /admin/activities
Execution exception (In {module:crud}/app/controllers/CRUD.java around line 135)
PersistenceException occured : org.hibernate.exception.ConstraintViolationException: could not insert: [models.users.hidden.ActivityModel]
play.exceptions.JavaExecutionException: org.hibernate.exception.ConstraintViolationException: could not insert: [models.users.hidden.ActivityModel]
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:290)
at Invocation.HTTP Request(Play!)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not insert: [models.users.hidden.ActivityModel]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1174)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:674)
at play.db.jpa.JPABase._save(JPABase.java:37)
at controllers.CRUD.create(CRUD.java:135)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:413)
at play.mvc.ActionInvoker.invokeControllerMethod(ActionInvoker.java:408)
at play.mvc.ActionInvoker.invoke(ActionInvoker.java:182)
... 1 more
... etc ...
What am I doing wrong? :S

Apparently it was because there was a different class containing the following code:
#OneToMany(cascade = CascadeType.ALL, mappedBy="id")
public Collection<ActivityModel> activities;
In which the 'mappedBy="id"' is the source of the problem.
Remove this and it all works :)

Related

JPA query receive column name not valid

I need to execute a very simply JPA Query
but I receive the error message "column name not valid".
Obviously, if I execute manually the query it works fine, but not if I use JPA.
This is my repository class:
#Repository
public interface OrdersRepositoryPayId extends JpaRepository<OrdersEntityPayId, Long> {
#Query(value="select trackid from orders where payid=:payid" , nativeQuery=true)
OrdersEntityPayId getOrdersByPaymentId(#Param("payid") String payid);
}
And this is the Entity class:
#Entity
#Table(name = "ORDERS")
public class OrdersEntityPayId {
#Id
private Long orderid; // These are the table fields name
private String payid;
private String trackid;
// Getter and setter ....
}
And this is the oracle tabel primaryKey:
Database is Oracle. Table name is ORDERS. PrimaryKey is ORDERS.ORDERID NUMBER(16,0)
Could you pls indicate what I'm wrong?
Below the error I received:
org.springframework.orm.jpa.JpaSystemException: could not execute
query; nested exception is
org.hibernate.exception.GenericJDBCException: could not execute query
at
org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:331)
at
org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)
at
org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:551)
at
org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at
org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
[..] [..] Caused by: java.sql.SQLException: Nome colonna non valido
at
oracle.jdbc.driver.OracleStatement.getColumnIndexPrimitive(OracleStatement.java:4257)
at
oracle.jdbc.driver.OracleStatement.getColumnIndex(OracleStatement.java:4215)
at
oracle.jdbc.driver.InsensitiveScrollableResultSet.findColumn(InsensitiveScrollableResultSet.java:299)
at
oracle.jdbc.driver.GeneratedResultSet.getLong(GeneratedResultSet.java:626)
[...]
Thanks in advance.

JPA issue: trouble with persisting an association class that has an EmbeddedId composite key

I'm quite new to learning JPA and looking to get some insight on the following: I'm having trouble persisting rows of an association class into its respective table using JPA.
The association class 'movie_showings' is a 1-to-many with 'movies' on one side and 1-to-many with 'theaters' on the other side. As you can imagine, there is a composite primary key composed of the foreign keys from the latter two classes. I chose to implement that using an Embeddable class, 'movie_showings_pk'.
At this point, instantiating an object of the association class, passing it a movie and a theater to construct a PK is not an issue. Calling the functions to associate the 'movie_showing' instance to 'theaters' and 'movies' respectively is not an issue. However, when I go to PERSIST the 'movie_showings' instance in the database using the entityManager, I get a constraint violation exception that I don't quite understand:
Exception in thread "main" javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.7.1.v20171221-bd47e8f): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: Column 'MOVIES_MID' cannot accept a NULL value.
Error Code: 20000
Call: INSERT INTO movie_showings (DATEOFLASTSHOW, OPENINGDATE, MOVIE, THEATER, MOVIE_MID, THEATER_TID) VALUES (?, ?, ?, ?, ?, ?)
bind => [6 parameters bound]
Query: InsertObjectQuery(PK => MOVIE ID > 3 THEATER ID > 1 Opening Date: Jan-15-2020)
Here is the function definition I use to test this out:
private void loadInitialMovieShowings ()
{
System.out.println ("LOADING movie_showings...");
List <Movie> allMovies = entityManager.createNamedQuery(Movie.FIND_ALL, Movie.class).getResultList();
List <Theater> allTheaters = entityManager.createNamedQuery(Theater.FIND_ALL, Theater.class).getResultList();
Theater spectrum = null;
for (Theater theater : allTheaters)
if (theater.getName().contains("Irvine Spectrum"))
spectrum = new Theater (theater);
List <Movie> allStarWars = new ArrayList<>();
for (Movie movie : allMovies)
if (movie.getTitle().contains("Star Wars"))
allStarWars.add(movie);
for (Movie movie : allStarWars)
{
MovieShowing temp = new MovieShowing (movie, spectrum,
new GregorianCalendar(2020, 00, 15),
new GregorianCalendar(2020, 04, 04));
movie.addMovieShowing(temp);
spectrum.addMovieShowing(temp);
entityManager.persist (temp);
}
}
This is (part of) the association class:
public class MovieShowing
{
// QUERY STRING(S)
public static final String FIND_ALL_ID = "MovieShowing.FIND_ALL_ID";
public static final String FIND_ALL_INFO = "MovieShowing.FIND_ALL_INFO";
#EmbeddedId
private Movie_Showings_PK ms_id;
#Temporal (TemporalType.DATE)
private GregorianCalendar openingDate;
#Temporal (TemporalType.DATE)
private GregorianCalendar dateOfLastShow;
// ASSOCIATION(S)
#ManyToOne
private Theater theater;
#ManyToOne
private Movie movie;
// CONSTRUCTORS
public MovieShowing () { }
public MovieShowing (Movie movie, Theater theater, GregorianCalendar opening, GregorianCalendar closing)
{
ms_id = new Movie_Showings_PK(movie, theater);
setMovie(movie);
setTheater(theater);
setOpeningDate(opening);
setDateOfLastShow(closing);
}
...
This is the Embeddedable class:
public class Movie_Showings_PK
{
#Basic
private Long theater;
#Basic
private Long movie;
// CONSTRUCTORS
public Movie_Showings_PK () {}
public Movie_Showings_PK (Movie movie, Theater theater)
{
this.movie = movie.getMID ();
this.theater = theater.getTID ();
}
...
I'm sure the answer is right in my face but I've been scratching my head for a couple days trying to figure it out... Thanks for any insight, all!
AH. I was an idiot. Inside my 'Movie' class, I had mistakenly put a separate #ManyToMany association with 'Theater' in a previous attempt to link up these two tables. After removing it, everything worked out fine. Chalk this one up to growing pains..

Spring Data JPA : How save data into database using save() of jpaRepository

I created one spring Application. I am trying to save data into database using save method of JPA Repository. i am getting Error null value in column "id" violates not-null constraint
HomeController
#RestController
public class HomeController
{
#Autowired
public userRepository repository;
#RequestMapping(value="/save2",method=RequestMethod.POST )
public String save1(#ModelAttribute user us)
{
repository.save(us);
return "sucessfull";
}
}
user
#Entity
#Table(name="user", schema="new")
public class user implements Serializable
{
private static final long serialVersionUID = -2956665320311624925L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer id;
#Column(name="uname")
public String uname;
#Column(name="pass")
public String pass;
Table Script
Through Postman I am trying to Insert following data
I am getting this error
org.postgresql.util.PSQLException: ERROR: null value in column "id" violates not-null constraint
Can Any one tell me what i am doing wrong in above code
I see couple of issues here.
First, replace your #ModelAttribute with #RequestBody since you're sending a JSON request, it is wise to use the latter. (Read up here and here). In your case, the values from request is not passed to repository save method including Id value. That's the reason you're getting not null constraint error.
Second, since you're using GenerationType.IDENTITY strategy, you should use serial or bigserial type to let Postgres to generate your primary key.
Read up nicely written answers on IDENTITY strategy here
You defined id as an Integer field in your model class. Try to pass the value in the json as an Integer, not as a String.
{
"id": 1,
"uname": "abc",
"upass": "abc"
}

(JDBI/Dropwizard) PSQLException when retrieving auto-incremented id from PostgreSQL

I'm trying to set up a dropwizard project but I'm stuck. When I try to get the auto generated id field with #GetGeneratedKeys then I'm getting the following Exception:
org.postgresql.util.PSQLException: Bad value for type long : foo.
The request is a simple JSON Request
{"name":"foo"}
The INSERT into the database is successful but it seems that the statement returns the value of the name instead of the generated id. How can I solve this?
I use postgresql, and the table project contains a primary key field "id" with nextval('project_id_seq'::regclass). Here are the POJO, DAO and Resource Classes I use:
public class Project {
private long id;
private String name;
public Project() { // Jackson deserialization }
public Project(long id, String name) {
this.id = id;
this.name = name;
}
...
}
#RegisterMapper(ProjectMapper.class)
public interface ProjectDAO {
#SqlUpdate("insert into project (name) values (:name)")
#GetGeneratedKeys
public long insert(#Bind("name") String name);
}
#Path("/project")
#Consumes({MediaType.APPLICATION_JSON})
#Produces({MediaType.APPLICATION_JSON})
public class ProjectResource {
ProjectDAO projectDAO;
public ProjectResource(ProjectDAO personDAO) {
this.projectDAO = personDAO;
}
#POST
#Timed
public Response add(#Valid Project project) {
long newId = projectDAO.insert(project.getName());
project.setId(newId);
return Response.status(Response.Status.CREATED)
.entity(project).build();
}
}
===============
UPDATE
I just figured out that this relates to the fact that my id column isn't the first column in my table. The column name is. The problem occurs because #GetGeneratedKeys is using org.skife.jdbi.v2.sqlobject.FigureItOutResultSetMapper which is using org.skife.jdbi.v2.PrimitivesMapperFactory which returns org.skife.jdbi.v2.util.LongMapper.FIRST. This mapper is calling
java.sql.ResultSet.getLong(1) through the method extractByIndex(...) to retrieve the generated id, which isn't the id in my case...
I'll fix the issue by reorganizing the columns in the database, but I'd like to have a robust implementation if possible: Is there a way to specify the column name of the id column when using the #GetGeneratedKeys Annotation? (The org.skife.jdbi.v2.util.LongMapper class contains a also method called extractByName(...))
This is an issue in the jdbi implementation and is fixed in a newer version as described in https://github.com/jdbi/jdbi/issues/114

Assigning Sequences for all JPA entities using SessionCustomizer

I am trying to use a SessionCustomizer to automatically generate Sequences in EclipseLink which already exist in the database following a special naming convention. For example an entity called Item is mapped to a table called ITEMS which has a four letter alias ITEM and a database sequence called ITEM_ID_SEQ for unique ID generation.
I am using an annotation as a marker to hold the alias name on the entity class because we are using it for other purposes, too:
package jpa.namingsupport;
// imports omitted
#Target(TYPE)
#Retention(RUNTIME)
public #interface Alias {
String name();
}
Entities look like this:
package jpa.entities;
// imports omitted
#Entity
#Table(name = "ITEMS")
#Alias(name = "ITEM")
public class Item {
#Id
private Long id;
#Version
private Long version;
private String name;
// setters and getters omitted
}
Using a SessionCustomizer registered correctly and verified running on startup to create and add the Sequences to the entities:
package jpa.namingsupport;
// imports omitted
public class AliasCustomizer implements SessionCustomizer {
#Override
public void customize(Session session) throws Exception {
Map<Class, ClassDescriptor> entities = session.getDescriptors();
for (Class entity : entities.keySet()) {
customizeSequence(aliasNameFor(entity), entities.get(entity), session);
}
}
private String aliasNameFor(Class entity) {
Alias alias = (Alias) entity.getAnnotation(Alias.class);
return alias.name();
}
private void customizeSequence(String alias, ClassDescriptor descriptor, Session session) {
NativeSequence sequence = new NativeSequence(underscores(alias, "ID", "SEQ"), 1);
session.getLogin().addSequence(sequence);
descriptor.setSequenceNumberName(sequence.getName());
descriptor.setSequenceNumberField(descriptor.getPrimaryKeyFields().get(0));
descriptor.setSequence(sequence);
}
private String underscores(String... parts) {
return StringUtils.arrayToDelimitedString(parts, "_");
}
}
But when I am running my tests the ID is not assigned from the Sequence before saving:
[EL Warning]: 2013-07-14 20:32:32.571--UnitOfWork(1908148255)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.h2.jdbc.JdbcSQLException: NULL nicht zulässig für Feld "ITEM_ID"
NULL not allowed for column "ITEM_ID"; SQL statement:
INSERT INTO ITEMS (ITEM_NAME, ITEM_VERSION) VALUES (?, ?) [23502-172]
Any hints and ideas what I am missing in my code? What I am seeing is that there is no reference to the ITEM_ID column in the generated insert statement.
Why don't you just put #GeneratedValue(strategy=SEQUENCE, generator="ITME_ID_SEQ") on your id?
For your customizer, don't call descriptor.setSequence(), this should be done be initializaiton.
The SQL is expecting the id to being using an IDENTITY value, you need to configure your table for this. If you want to use SEQUENCE instead, then pass false into new NativeSequence(name, increment, false). H2 supports both IDENTITY and SEQUENCE, and NativeSequence defaults to using IDENTITY, false means SEQUENCE.