Hibernate "could not get next sequence value" oracle - 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?

Related

Unable to insert into table in hibernate

I am trying to create new table and join with ManyToOne relation with my existing table
below is my implementation
New table
#Entity(name="request_city_id")
#Table(uniqueConstraints={#UniqueConstraints{columnNames={"request_id","cityId"})})
#Data
#NoArgsConstructor
#FieldDefault(level=AccessLevel.PRIVATE)
public class RequestCityId{
#GenratedValue(strategy=SEQUENCE, generator="seq_req_city_id")
#SequenceGenerator(name="seq_req_city_id", allocationSize=1)
#Column(name="rc_id")
#Id
long id;
#ManyToOne
#JoinColumn(name="request_id")
Request request;
String cityId;
String status
}
Existing table
#Entity(name="request")
#Data
#NoArgsConstructor
#FieldDefault(level=AccessLevel.PRIVATE)
public class Request{
String frequency
#GenratedValue(strategy=SEQUENCE, generator="seq_req_d")
#SequenceGenerator(name="seq_req_id", allocationSize=1)
#Column(name="request_id")
#Id
long id;
#OneToMany(cascade={ PERSIST, MERGE}, mappedBy="request", fetch=EAGER)
Set<RequestCityId> requestCityIds;
}
but when I am trying to insert into my new table I see my hibernate query gets stuck and just gets timed out after sometime, I am not sure what I am doing wrong here? If I just kep cascade type MERGE then getting
Hibernate Error: a different object with the same identifier value was already associated with the session
First you should create an getters and setters method to each entity.
Request Class
Request City Id Class
this code creates the tables and also saves the data into the table.
Using #Data in entity classes in not recommended because it may cause some problems with jpa as mentioned here.

Spring data jdbc mapping not working if use not primary key

I have 2 entities:
#Data
#Table("main_entities")
public class MainEntity {
#Id
private Long id;
private String anotherId;
#MappedCollection(idColumn = "main_entity_id")
private SecondEntity secondEntity;
}
#Data
#Table("second_entities")
public class SecondEntity {
#Id
private Long id;
private Long mainEntityId;
}
And exists the repository:
public interface MainEntityRepository extends CrudRepository<MainEntity, Long> {
#Query("SELECT * FROM main_entities WHERE another_id = :anotherId")
Optional<MainEntity> findByAnotherId(#Param("anotherId") String anotherId);
}
When I use the MainEntityRepository#findById(Long) - the SecondEntity is available, when I use the MainEntityRepository#findByAnotherId(String) - the SecondEntity is null
Update 2021.12.15:
if set the
#MappedCollection(idColumn = "main_entity_id")
private Set<SecondEntity> secondEntities;
Its allows to get the mapped collection via MainEntityRepository#findByAnotherId(String)
Spring Data JDBC loads 1:1 relationships with a single join and expects you to do the same when you specify a custom query.
In order to avoid ambiguities you have to use column aliases which prefix the columns with the property name of the 1:1 relation ship plus an _.
So your select should look like this:
SELECT M.ID, M.ANOTHER_ID, S.ID AS SECONDENTITY_ID, S.MAIN_ENTITY_ID AS SECONDENTITY_MAIN_ENTITY_ID
FROM MAIN_ENTITIES M
JOIN SECOND_ENTITIES S
ON M.ID = S.MAIN_ENTITY_ID
WHERE ANOTHER_ID = :anotherId
I created a complete example.
Side note: I recommend not to have an id on the non-aggregate-root entities, nor to have the reference back to the aggregate root in these entities. See Spring Data JDBC - How do I make Bidirectional Relationships?
so you want to fetch the second entity together with your main entity with your custom method?
I thinkt it has to do with the fetch type of your main entity. It is lazy by default and if you want to load both entitys you can try to set the fetch type to eager for the second entity field in your main entity. But be aware that this is not always the best option but rather a quick fix. See here for more information about fetch types.
You can also try using the join fetch as described in the accepted answer here to achieve your requested behaviour. I think that this would be the best solution.
I hope I got your question right if not please try to explain with further detail.

Heroku shows Whitelabel Error Page but not on localhost

I have a Spring boot application with PostgreSQL. The app run very well on localhost with all the data from the PostgreSQL. I have successful upload the app to Heroku and migrated the database to Heroku PostgreSQL. The problem is when I click some of the links that retrieve data from PostgreSQL shows a White Error page. But on localhost every thing works fine.
Below is the Controller that link to the White Error Page.
#Controller
public class MahubiriController {
#Autowired
private MisaleRepository misaleRepository;
#GetMapping("/masomo/somolaleo")
public String masomoAngalia(Model model){
model.addAttribute("masomoYote", misaleRepository.findAllOrderByDateDesc() );
return "masomo";
} }
Below is the repository
#Repository
#Transactional
public interface MisaleRepository extends JpaRepository <Misale, String> {
#Query(value ="SELECT * FROM misale ORDER BY date DESC" , nativeQuery = true)
public List<Misale> findAllOrderByDateDesc();
}
Below is the Entity for the particular object
#Entity
#Table(name = "misale")
public class Misale {
#Id
#Column(name ="date")
private String date;
#Lob
#Column(name ="first_reading", columnDefinition="text")
private String firstReading;
#Lob
#Column(name ="second_reading", columnDefinition="text")
private String secondReading;
// Constructors, getter and setters
}
Below is the Query used to create the particular table on Postgresql
CREATE TABLE misale(date VARCHAR(20) NOT NULL PRIMARY KEY,
first_reading TEXT NOT NULL,
second_reading TEXT,gospel TEXT NOT NULL);
What could possibly be wrong on Heroku to lead to a White Error Page and not on a local host.
Update :
After implementing the Exception handling as suggested by # krishnkant jaiswal, I receive message "Unable to access lob str…le to access lob stream" as below.
timestamp "2021-04-03T01:26:43.791+00:00"
message "Unable to access lob stream; nested exception is org.hibernate.HibernateException: Unable to access lob stream"
details "uri=/masomo/somolaleo"
With the help of Exception handling and a long research, On my side it shows that you cannot use
#Lob and #Column(columnDefinition="text")
So I had to remove #Lob and leave #Column(columnDefinition="text")
#Column(columnDefinition="text")
Now I cloud retrieve the data from PostgreSQL without error.
Hope it might help someone else in future.

Hibernate doesn't return manually INSERTed rows

I'm having an issue with my jpa repository doesn't return rows that I've manually inserted into the database (Oracle) via good old SQL
Insert into SYSTEM.USER (ID,CREDENTIALS,ISADMIN) values (USERSEQ.nextval,'foo',1);
My Jpa Repository
#RepositoryRestResource
public interface UserRepository extends JpaRepository<User, Long> {}
User entity
#Data
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idgen")
#SequenceGenerator(initialValue = 1, allocationSize = 1, name = "idgen", sequenceName = "userseq")
private Long id;
#NotNull
private String credentials;
private boolean isAdmin;
}
The super weird thing is that entries that I've inserted via the REST interface works!
So if I create:
User A via REST API
User B via SQL statement
User C via REST API
The result of GET /api/users is A, C
After pulling out all my hair. I think I've narrowed it down to the Flashback feature Oracle has. As only A and C has entries in the Flashback. So Hibernate must do some magic behind the scene.
So my question is. How do I insert a row using SQL so it get a flashback entry also.
If the flashback thing isn't the problem. How do I make Hibernate return all the rows then?
while you are executing the SQL query in Oracle Sql Developer that time it is working own session. and JPA is working own session. i.e. JPA is not able to access the SQL query's records.
solution
Insert into SYSTEM.USER (ID,CREDENTIALS,ISADMIN) values (USERSEQ.nextval,'foo',1);
after that just fire the COMMIT command in Oracle Sql Developer.
it is working for me.

JPA - Auto-generated field null after save

I have an Account entity and I'm trying to persist it using save function. My code:
#Override
public Account createAccount(String pin) {
Account account = new Account();
account.setBalance(0L);
account.setPin(pin);
return accountRepository.save(account);
}
Now my entity class has an autogenerated field called accountNumber. My entity class:
#Entity
#Table(name = "accounts")
#Data
public class Account {
#Column(name = "account_number", length = 32, insertable = false)
private String accountNumber;
private Long balance;
}
Now after calling save, the entity returned has accountNumber as null but i can see in the intellij database view that it is actually not null. All the other auto-generated fields like id etc are there in the returned entity just the accountNumber is null. Default value for accountNumber is set in the sql file :
ALTER TABLE accounts
ALTER COLUMN account_number SET DEFAULT DefaultValueSerializer(TRUE, TRUE, 12);
Here, DefaultValueSerializer is the function which is generating the account number.
I've tried other solutions available here like using saveAndFlush() etc, nothing worked in my case. What can be an issue?
As mentioned in comment Hibernate is not aware about what happens in database engine level so it does not see the value generated.
It would be wise to move generation of account number to JPA level instead of using db defaults.
I suggest you to study annotations #GeneratedValue and related stuff like #SequenceGenerator. That way the control of generating account number is in JPA level and there is no need for stuff like refreshing entity after save.
One starting point: Java - JPA - Generators - #SequenceGenerator
For non-id fields it is possible to generate value in method annotated with #PrePersist as other answer suggests but you could do the initialization already in the Accounts constructor .
Also see this answer for options.
You can create an annotated #PrePersist method inside the entity in which you set its fields to their default value.
That way jpa is going to be aware of the default.
There are other such annotation avaiable for different entity lifecycle event https://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/listeners.html
P.s. if you decide to go this way remember to remove the insertable = false
Use
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
for your IDs. And also leave your saving to saveAndFlush so you can immediately see the changes, If any. I'd also recommend separating IDs and account numbers. They should not be the same. Try debugging your program and see where the value stops passing around.

Resources