sequence does not exist, hibernate and JPA 2.1 - spring-boot

I am getting an error saying
`Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet] with root cause
java.sql.SQLSyntaxErrorException: ORA-02289: sequence does not exist`
This error happens when I try to create a user.
#RequestMapping(method = POST)
public UserDto createUser(#RequestBody userDto user) {
Preconditions.checkNotNull(user);
return Preconditions.checkNotNull(service.create(user));
}
I am however able to delete and get just not create nor update. What is also frustrating is I get no error when trying to update, it just doesn't so it.
I am not getting any real lead on where to look. I have tried many different methods to resolve this with no avail.
I found a post that had this:
#Id
#GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQUENCE1")
#SequenceGenerator(name="SEQUENCE1", sequenceName="SEQUENCE1", allocationSize=1)
private int user_id;
At this link: SOF link
It is complaining about this entity which I generated with netbeans and I am currently using Intellij. Any advice would be appreciated.

The code that creates new Campaign entity seems to be incorrect.
public CampaignDto create(CampaignDto campaignDto) {
Campaign campaign = mapper.mapReverse(campaignDto);
System.out.println(campaign.toString());
// Following 2 lines must be added to obtain and use managed Shop entity
Shop existingShop = shopRepository.findOne(campaignDto.getShopId());
campaign.setShop(existingShop);
campaign = campaignRepository.save(campaign);
CampaignDto createdCampaign = mapper.map(campaign);
return createdCampaign;
}

It looks like you might not be setting Campaign.shopId field when creating new Campaign.
#JoinColumn(name = "SHOP_ID", referencedColumnName = "SHOP_ID")
#ManyToOne(optional = false)
private Shop shopId;
You might want to rename this field to just shop to make it clear what it holds as it's not just an identifier.
Depending on how you are persisting new objects you might need to add CascadeType.ALL on #ManyToOne to ensure that a new Shop is persisted together with a new Campaign.
#ManyToOne(optional = false, cascade = CascadeType.ALL)

Go to your application property file and put
hibernate.hbm2ddl.auto=true; It might be helpful Hibernate created this sequence and added a new row

Related

Repository.saveAll throws InvalidDataAccessApiUsageException

I query a Bugzilla REST API with Spring, which returns a JSON object with the following structure:
https://bugzilla.mozilla.org/rest/bug/35
I have the following JPA class (excerpt):
#Entity
#Table
public class bug {
....
#ManyToOne (fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn (name = "assigned_to_user_id")
#SerializedName ("assigned_to_detail")
protected BugUser assignedTo;
#ManyToMany (cascade = CascadeType.ALL)
#JoinColumn (/ * ... shortened ... * /)
#SerializedName ("c_detail")
protected List <BugUser> cc;
...
}
The web service call takes place with the help of the Spring remainder template. Then the object is mapped from the rest template into my JPA class. However, when the data set is persisted by the Spring repository, I get the following exception:
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException:
Multiple representations of the same entity [BugUser # 2] are being
merged. Detached: [BugUser # 21]; Detached: [BugUser # 12];
As soon as I only comment one member variable of type BugUser in the Bug class, everything works.
How can I work around this problem?
You will have to make sure there is only one object with the same primary key. You can go through the list before merging and do something like the following:
Bug b = ...
BugUser assignee = b.assignedTo;
ListIterator<BugUser> iter = b.cc.listIterator();
while (iter.hasNext()) {
if (assignee.id.equals(iter.next().id) {
iter.set(assignee);
}
}
This way you ensure that the objects in the list of the same primary key are the same as the assignee. That is exactly why Hibernate complains.

CRUDRepository findBy foreign key id causing exception: Unable to locate Attribute with the the given name [classroomId] on this ManagedType

I am getting an exception when creating a custom findBy method by a foreign key.
Entity class:
#Entity
#Getter
#Setter
public class Thread {
private #Id #GeneratedValue Long id;
private String subject;
#ManyToOne(fetch = FetchType.LAZY)
#JsonIgnore
private Classroom classroom;
protected Thread() {}
public Long getClassroomId() {
return this.classroom.getId();
}
}
ThreadRepository class:
public interface ThreadRepository extends CrudRepository<Thread, Long> {
List<Thread> findByClassroomId(Long id);
}
I get the exception:
java.lang.IllegalArgumentException: Unable to locate Attribute with the the given name [classroomId] on this ManagedType [com.futurerprood.unicycleservice.entity.threads.Thread]
But the exception goes away if I remove the getClassroomId() in the Thread class. I have this function so that the json serialization will pick up only the classroom id instead of the whole classroom object in an endpoint response.
Why is this function causing the foreign key unable to be found?
You can do one of the following:
Provide the query to the repository method
#Query("select e from Thread t join t.classroom c where c.id = :id")
List<Thread> findByClassroomId(Long id);
Rename the repository method
List<Event> findByClassroom_Id(Long id);
Update
Explanation as to why these two are working
First, have a look at https://docs.spring.io/spring-data/jpa/docs/1.4.3.RELEASE/reference/htmlsingle/#d0e391 and understand how property traversal based on method name happens in Spring data JPA in order to generate the query and how ambiguity resolution is recommended.
In the first one, we tell spring data, it does not need to do property traversal to generate the JPA query as we are giving the query so it does not get any ambiguity.
In the second, as recommended in the reference, we are resolving the ambiguity for Spring Data JPA by telling it to go to Classroom object first. But as #crizzis pointed out under the question comment, Spring data should have treated it as ambiguity in the first place

How to use #RestController (Spring) with a child List of object

I'm trying to create a REST service with Spring.
Everything works until I try to add a List of object (CartItem) to my main object (Cart).
This is my main object
#Entity
#Table(name="cart")
public class Cart implements Serializable{
...
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Id
#Column(name="id")
private Integer id;
/*when I add this I get the error. If I remove this, the
REST service works*/
#OneToMany(mappedBy="cart", fetch = FetchType.EAGER)
private List<CartItem> cartItems;
//getter, setter, constructors, other fields ecc.
}
This is the object inside the List:
#Entity
#Table(name="cart_item")
public class CartItem implements Serializable{
...
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Id
#Column(name="id")
private Integer id;
#OneToOne(targetEntity = Product.class, cascade = CascadeType.ALL)
#JoinColumn(referencedColumnName="productId", name="product_id" )
private Product product;
#ManyToOne
#JoinColumn(name="cart_id", nullable=false)
private Cart cart;
//getter, setter, constructors, other fields ecc.
}
This is my controller
#RestController
#RequestMapping(value="rest/cart")
public class CartRestController {
...
#RequestMapping(value = "/", method = RequestMethod.GET)
public List<Cart> readAll() {
return cartService.read();
}
...
}
I get this error:
SEVERE: Servlet.service() for servlet [dispatcher] in context with path
[/webstore] threw exception [Request processing failed; nested exception
is org.springframework.http.converter.HttpMessageNotWritableException:
Could not write JSON: Infinite recursion (StackOverflowError); nested
exception is com.fasterxml.jackson.databind.JsonMappingException:
Infinite recursion (StackOverflowError) (through reference chain:...
I suppose that I had to manage the List inside the Cart object in a particular manner, maybe because i'm using JPA, but I still didn't find a solution on the internet.
Can anyone help me?
This is a serialization recursion problem, it happens because CartItem has a bidirectional mapping back to Cart. So what happens is that
a Cart gets serialized to JSON
all the CartItems inside it get serialized to JSON
the Cart property inside CartItem get serialized to JSON
the CartItems inside the cart get serialized to json, etc. etc.
You will probably want to exclude the CartItem.cart field from serialization by marking it with the #JsonIgnore annotation.
It is only too easy to expose far too much information to the outside world if you use JPA entities directly inside your webservices. Jackson actually has a useful feature called a JsonView which allows you to define which properties get exposed, you can even tailor it per webservice call if you want.
Never ending list? Did you mean a stackOverFlow exception?
If the situation is just like I said,then you should check something like fetch type and the entities' toString() or equal() method or something like that.
For example,there are to entities named A and B and their relationship is one to many(A is the one).If you config both of their fetchType as Eager,then when jpa query A,it will query B too.But B also contains A,so jpa will query A again.This kind of circle loop will cause a stackOverFlow.
By the way, how about providing more info about your problem like the Exception name?It's too hard for me to give you a specific solution,All I can do is to tell you some experiences I have met before.
Well,I created a small project with SpringBoot 2.1.0 and MySql.
It's my cartItem
public class CartItem {
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Id
#Column(name="id")
private Integer id;
#JsonIgnore
#ManyToOne
#JoinColumn(name="cart_id", nullable=false)
private Cart cart;
}
and my cart:
public class Cart {
#GeneratedValue(strategy= GenerationType.IDENTITY)
#Id
#Column(name="id")
private Integer id;
#OneToMany(mappedBy="cart", fetch = FetchType.EAGER)
private List<CartItem> cartItems;
}
Controller is as same as you wrote.After adding a #JsonIgnore to cart filed of CartItem,circle loop is over(before i do that,the program did had a circle loop problem).
Every time you use jpa with #oneToMany,#ManyToOne or #ManyToMany,you should be careful about this problem.This circular reference case could happen when instantiating a object, printing a object or something like this.And of course there is a lot of way to solve it like changing fetch type to LAZY,adding #JsonIgnore,overriding toString() and equal() method.

Spring batch can't find entity persisted while processing

In one of our spring batch jobs, we create additional entities (CompanyProfile) during processing and persist them to the DB (in a separate transaction). These entities are referenced by other entities (Vacancy), which will be persisted by the writer, but unfortunate the writer fails with this error:
Caused by: javax.persistence.EntityNotFoundException: Unable to find com.company.CompanyProfile with id 1409881
The model is as follows:
#Entity
public class Vacancy {
#ManyToOne(fetch = FetchType.EAGER, optional = true)
#JoinColumn(name = "company", nullable = true)
private CompanyProfile company;
...
}
#Entity
public class CompanyProfile {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
}
In the processor we have this:
CompanyProfile company = companyProfileService.handleCompany(compName);
vacancy.setCompany(company);
Where the method companyProfileService.handleCompany() is annotated with #Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW )
I'm sure the CompanyProfile gets persisted - I can see it in the DB, but when the Vacancy gets saved by the ItemWriter, it fails with the above exception. (also, note that the id of the persisted entity is mention in the exception above)
Do you see any reason why the writer would fail in this case?
With information you gave us my guess is that transaction opened by SB is unable to see data persisted by companyProfileService.handleCompany() method because service component uses a different transaction than SB ones; you have to check database ISOLATION_LEVEL property

Hibernate "could not get next sequence value" oracle

i get this error could not get next sequence value when I try to save this Entity with Hibernate:
package beans;
import javax.persistence.*;
#Entity
#Table(schema = "EVGENY")
public class Article {
#SequenceGenerator(name="ArticleGen", sequenceName="ARTICLESEC")
#Id
#GeneratedValue(generator= "ArticleGen")
private int id;
#Column(name="title")
private String title;
#Column(name="text")
private String text;
#Column(name="postat")
private String postat;
#ManyToOne
#JoinColumn(name = "USER_ID")
private UserAcc user;
public Article(){
}
Get Set...
}
insert into article (title) values('asdfaf');
in Oracle SQL Developer this insert into article (title) values('asdfaf'); works well.
if i set id variable explicitly ( Article a = new Article();a.setId(3); )
everything is OK. I double checked the name of the sequence.
Check user permissions on the sequence. Most of the time it is grant issue
I know a lot of reasons to get this exception. Maybe you can check the questions and give me some more details about your problem:
check if the 'hibernate.dialect' is set to Oracle?
permission on sequence ok (schemata, select etc.)?
is there some trigger behind the table and throwing plsql error?
some other plsql that could break the insert?
is the transaction broken?
was there an exception (sometimes silent) somwhere before the call of create (like stale state or out of bounce) so that transaction is marked for rollback?
is there a connection is erroneous error before exception?
is the entity maybe already attached (check with contains)?
do you use spring or another framework where you can add exception resolvers or translators?
which version of oracle database do you use? 10 or 11? and are the used drivers correct?
is there a findSingle call before that does not return any value?

Resources