I'm trying to save my entity but this error occurs to me after changing the class ID from long to Long
I don't know why but hibernate doesn't save the object and thymeleaf sees that the ID field is null
Should I change it back to long ?
(Something strange)
I opened the debugger to see where the problem occurs
after calling EntityManager.persist() an ID is assigned to the object but it throws an exception saying that the object couldn't be saved
Thanks in advance
It means hibernate is not able to generate an id for the record.
Ensure that you are using #Id annotation and #GeneratedValue(strategy=GenerationType.AUTO) on id field and have proper getter/setters.
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
Related
It should be easy. Oracle has defined "generate always" for an id column. So there is no need to add this id to the insert statement. How do i define my entity that it is handling right.
#Entity
public class Example {
#Id
#GeneratedValue // if i remove this annotation than hibernate complains that i need to set it manually
#Column(name="ID", insertable=false, updatable=false)
private Long id;
}
in the error message i see that it still tries to add the id to the query.
My work-around for the column. Add the #id to an other column and remove the id column from entity definition :-D
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.
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.
I have model class as below in my entity class
#Entity
#Table(name="TblKnow")
public class Know {
#Id
#Column(name="IdKnow")
private Double IdKnow;
The ID is autogenerated by database, so i do not need to fill the ID.
But when i put the value id as null i get below exception
:ids for this class must be manually assigned before calling save(): com.melk.spring.model.Know
First set your id type to Long, then add #GeneratedValue(strategy=GenerationType.IDENTITY), don't forget to add a getter & setter for this field.
#Id
#Column(name="IdKnow")
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long IdKnow;
Make sure that on your DB the id column is of type BIGINT
I'm working on a Hibernate/Spring application to manage some movies.
The class movie has a many to many relationship with the class genre.
Both of these classes have generated id's using the GeneratedValue annotation.
The genre is saved through the movie object by using #Cascade(CascadeType.SAVE_UPDATE)
I have placed a unique constraint on the genre's type attribute (which is it's name; "Fantasy" for example).
What I would like to do now is have Hibernate check if there is already a genre with type "Fantasy" and if there is, use that genre's id instead of trying to insert a new record.
(The latter would obviously throw an error)
Finally what I need is something like select-before-update but more like select-before-save.
Is there such a function in Hibernate?
Some code:
Movie class
#Entity
public class Movie {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
private String name;
#Lob
private String description;
#Temporal(TemporalType.TIME)
private Date releaseDate;
#ManyToMany
#Cascade(CascadeType.SAVE_UPDATE)
private Set<Genre> genres = new HashSet<Genre>();
.... //other methods
Genre class
#Entity
public class Genre {
#Column(unique=true)
private String type;
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private int id
....//other methods
You may be over-thinking this. Any select-before-update/select-before-save option is going to result in 2 DB round trips, the first for the select, and the second for the insert if necessary.
If you know you won't have a lot of genres from the outset, you do have a couple of options for doing this in 1 RT most of the time:
The Hibernate second-level cache can hold many if not all of your Genres, resulting in a simple hashtable lookup (assuming a single node) when you check for existence.
You can assume all of your genres are already existing, use session.load(), and handle the new insert as a result of the row not found exception that gets thrown when you reference a genre that doesn't already exist.
Realistically, though, unless you're talking about a LOT of transactions, a simple pre-query before save/update is not going to kill your performance.
I haven't heard of such a function in Hibernate select-before-update/select-before-save
In situations like these you should treat Hibernate as if it was JDBC.
First if you want to know if you even have such a Genre you should query for it.
if you do. then the SAVE_UPDATE will not create a new one when you add it to a movie.
if you don't, Hibernate will create a new Genre row in the database and add the connection to the many_to_many table for you.