Here's what I had to write to get UUID working as a primary key, with full UUID types (on all ends) in hibernate. Since this relies on some Hibernate specific code, what would I have to do to convert this code to work on eclipselink?
package com.lm.model;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Type;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.UUID;
#Entity
#Table(name = "tasks")
public class Task {
#Id
#NotNull
#Type(type = "pg-uuid")
#GeneratedValue(generator = "myUUIDGenerator")
#GenericGenerator(name = "myUUIDGenerator", strategy = "uuid2")
#Column(name = "task_id", columnDefinition = "uuid")
private UUID id;
#NotNull
#Size(min = 1, max = 100)
private String description;
public String getDescription() {
return description;
}
public void setDescription(final String description) {
this.description = description;
}
public UUID getId() {
return id;
}
public void setId(final UUID id) {
this.id = id;
}
}
Related
package com.springboot.blog.entity;
import lombok.*;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
#Data
#AllArgsConstructor
#NoArgsConstructor
#Entity
#Table(name = "posts")
public class Post {
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Id
private Long id;
#Column(name = "title", nullable = false)
private String title;
#Column(name = "description", nullable = false)
private String description;
#Column(name = "content", nullable = false)
private String content;
#OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Comment> comments = new HashSet<>();
}
Here is the Post class
package com.springboot.blog.payload;
import lombok.Data;
import java.util.Set;
#Data
public class PostDTO {
private Long id;
private String title;
private String description;
private String content;
private Set<CommentDTO> comments;
}
Here is PostDTO class.
#Override
public PostDTO getPost(Long id) {
Post temp_post = postRepository.findById(id).
orElseThrow(() -> new ResourceNotFoundException("Post", "Id", id));
return mapToDTO(temp_post);
}
private PostDTO mapToDTO(Post post) {
return modelMapper.map(post, PostDTO.class);
}
I used mapToDTO method to convert post to postDTO.
But When I test it, the error message appeared.
{"timestamp":"2022-04-30T14:03:03.369+00:00","status":500,"error":"Internal Server Error","trace":"org.modelmapper.MappingException: ModelMapper mapping errors:\n\n1) Error mapping com.springboot.blog.entity.Post to com.springboot.blog.payload.PostDTO\n\n1 error\n\tat org.modelmapper.internal.Errors.throwMappingExceptionIfErrorsExist(Errors.java:380)\n\tat org.modelmapper.internal.
========================================================================================
** But when I replace the #Data annotation in class Post with #Getter, #Setter. It works perfectly! **
I am using Hibernate to fetch the JSON object from DB. I want that JSON object should contain all the details of the only top two of most recently created VGIs. But I don't know how to limit the result set and then sort on the basis of created date when no HQL query is used. It is fetching all the details from MySQL db.
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
#Entity
#Table(name = "vgi", catalog = "coworkee5")
public class VGI {
#ManyToOne
#JoinColumn(name = "employee_id", referencedColumnName = "id", insertable = false, updatable = false)
private Employees employees;
public Employees getEmployees() {
return employees;
}
public void setEmployees(Employees employees) {
this.employees = employees;
}
#OneToMany(cascade = CascadeType.ALL, targetEntity = VgiGoals.class, mappedBy = "vgi")
private List<VgiGoals> vgiGoals;
public List<VgiGoals> getVgiGoals() {
return vgiGoals;
}
public void setVgi_goals(List<VgiGoals> vgiGoals) {
this.vgiGoals = vgiGoals;
}
public VGI() {
}
#Id
#Column(name = "id")
private String id;
#Column(name = "title")
private String vgi;
#Column(name = "employee_id")
private String employee_id;
#Column(name = "created_on")
private String created;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getvgi() {
return vgi;
}
public void setvgi(String vgi) {
this.vgi = vgi;
}
public String getEmployee_id() {
return employee_id;
}
public void setEmployee_id(String employee_id) {
this.employee_id = employee_id;
}
public String getCreated() {
return created;
}
public void setCreated(String created) {
this.created = created;
}
}
Add #OrderBy annotation to sort like below.
#OneToMany(cascade = CascadeType.ALL, targetEntity = VgiGoals.class, mappedBy = "vgi")
#OrderBy("createdOn DESC")
private List<VgiGoals> vgiGoals;
NOTE : replace createdOn with your date field in VgiGoals class.
And for limit use below method in the query.
query.setFirstResult(1).setMaxResults(10);
In my app users can add movies to their watchlist. The movie data comes from an external API. Each movie has its own unique id. For example: Star Wars - A new hope has id 11. And Fight Club has id 550.
When a user adds a movie I pass the whole movie object from the front-end to the back-end:
Component:
createMovie(movie: Movie): void {
this._dataService.createMovie<Movie>({'name': 'Star Wars - A new hope', 'id': 11})
.subscribe((data) => this.movies.push(data),
error => () => {
'something went wrong';
},
() => {
// console.log(this.movies);
});
}
In this case I'm using example data.
Service:
public createMovie<T>(movie: Movie): Observable<T> {
return this.http.post<T>('/api/movies/', movie, {headers: this.getToken()});
}
The MovieController in the back-end:
#RequestMapping(value = "/", method = RequestMethod.POST)
public Movie createMovie(#RequestBody Movie movie){
return movieService.createMovie(movie);
}
The MovieService:
#Override
public Movie createMovie(Movie movie) {
User current_user = userService.getUser();
current_user.addMovie(movie);
userRepository.save(current_user);
return movie;
}
And the User model:
public void addMovie(Movie movie) {
movies.add(movie);
movie.getUsers().add(this);
}
When the movie is saved in the database it's saved with a unique id, starting from 1. How would I map the id from the front-end to the id of the object in my database? I could create another column "external_id" and map it to that, but I think that's a lesser solution than to use the id from the external API.
//edit. Added my movie and user model:
package com.movieseat.models;
import com.movieseat.model.security.User;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
#Entity(name = "Movie")
#Table(name = "movie")
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Integer id;
private String name;
private String description;
#ManyToMany(mappedBy = "movies")
private Set<User> users = new HashSet<>();
public Set<User> getUsers() {
return users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
User model:
package com.movieseat.model.security;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.movieseat.models.Movie;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
#Entity(name = "User")
#Table(name = "USER")
#JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class User {
#Id
#Column(name = "ID")
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
#SequenceGenerator(name = "user_seq", sequenceName = "user_seq", allocationSize = 1)
private Long id;
#Column(name = "USERNAME", length = 50, unique = true)
#NotNull
#Size(min = 4, max = 50)
private String username;
#Column(name = "PASSWORD", length = 100)
#NotNull
#Size(min = 4, max = 100)
private String password;
#Column(name = "FIRSTNAME", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String firstname;
#Column(name = "LASTNAME", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String lastname;
#Column(name = "EMAIL", length = 50)
#NotNull
#Size(min = 4, max = 50)
private String email;
#Column(name = "ENABLED")
#NotNull
private Boolean enabled;
#Column(name = "LASTPASSWORDRESETDATE")
#Temporal(TemporalType.TIMESTAMP)
#NotNull
private Date lastPasswordResetDate;
#ManyToMany(fetch = FetchType.EAGER)
#JoinTable(
name = "USER_AUTHORITY",
joinColumns = {#JoinColumn(name = "USER_ID", referencedColumnName = "ID")},
inverseJoinColumns = {#JoinColumn(name = "AUTHORITY_ID", referencedColumnName = "ID")})
private List<Authority> authorities;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Boolean getEnabled() {
return enabled;
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public List<Authority> getAuthorities() {
return authorities;
}
public void setAuthorities(List<Authority> authorities) {
this.authorities = authorities;
}
public Date getLastPasswordResetDate() {
return lastPasswordResetDate;
}
public void setLastPasswordResetDate(Date lastPasswordResetDate) {
this.lastPasswordResetDate = lastPasswordResetDate;
}
#ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
#JoinTable(name = "user_movie",
joinColumns = #JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "movie_id", referencedColumnName = "id")
)
private Set<Movie> movies = new HashSet<>();
public void addMovie(Movie movie) {
movies.add(movie);
movie.getUsers().add(this);
}
public void removeMovie(Movie movie) {
movies.remove(movie);
movie.getUsers().remove(this);
}
}
Hi I am new to this world.
I am making my own application with spring jpa hibernate.
I have an entity class. It works generally but it duplicates attributes.
My code look like this:
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.validation.constraints.NotNull;
#Entity
public class Event {
#Id
#GeneratedValue
private Integer id;
public Integer getId() {
return id;
}
#Column(nullable = false)
public void setId(Integer id) {
this.id = id;
}
/*------------------------------ title ------------------------*/
private String title;
#Column(nullable = false)
public String getTitle() {
return title;
}
#Column(nullable = false)
public void setTitle(String title) {
this.title = title;
}
/* [Note] I have two extra ids : event_id, eventId
- so these are not the case of the duplication. */
/*------------------- event_id -----------------------------*/
private String event_id;
public String getEvent_id() {
return event_id;
}
public void setEvent_id(String event_id) {
this.event_id = event_id;
}
/*-------------- eventId -------------------------------------*/
#Column(unique = true)
private String eventId;
public String getEventId() {
return eventId;
}
public void setEventId(String eventId) {
this.eventId = eventId;
}
/*------------------------------ publishedDate ------------------------------------------*/
private String publishedDate;
public String getPublishedDate() {
return publishedDate;
}
#Column(nullable = false)
public void setPublishedDate(String publishedDate) {
this.publishedDate = publishedDate;
}
/*--------------------------------- endTime -----------------------------------*/
private String endTime;
public String getEndTime() {
return endTime;
}
#Column(nullable = false)
public void setEndTime(String endTime) {
this.endTime = endTime;
}
/*-------------------------------- user ------------------------------------------*/
#ManyToOne
#JoinColumn(name="user_id")
private User user;
public User getUser() {
return user;
}
#Column(nullable = false)
public void setUser(User user) {
this.user = user;
}
Then when I check JPA diagram, it has duplication of several attributes.
I added my JPA diagram image(the red parts are duplicated)
This is my very first application with java programming.
so please understand, even I read documentation of the spring jpa,
It is difficult to figure out what exactly I did wrong in the code.
Any ideas? Thanks in advance.
The problem is that JPA expects either field level annotations or accessor (getters/setters) annotations. However you are using both, which basically isn't allowed. Remove all he annotations from the accessors and only put them on the fields.
Small hint on Java programming (styling) put your fields on top of the classes instead of between the accessors.
#Entity
public class Event {
#Id
#GeneratedValue
private Integer id;
#Column(unique = true)
private String eventId;
private String event_id;
#Column(nullable = false)
private String title;
#Column(nullable = false)
private String publishedDate;
#Column(nullable = false)
private String endTime;
#ManyToOne
#JoinColumn(name="user_id")
#Column(nullable = false)
private User user;
// Getters / Setters omitted
}
Remove the annotations from the accessors, also do you really want to set the id? I would expect not, so you might want to remove the setId method.
As mentioned in comments, your problem is that you are using two annotations for the same attribute, first in the field and then in its getter/setter, so you have to use only one of them, for example:
#Id
#GeneratedValue
private Integer id;
public Integer getId() {
return id;
}
#Column(nullable = false)
public void setId(Integer id) {
this.id = id;
}
Should be:
#Id
#GeneratedValue
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
And it's wrong to usnnotations here with both getter and setter:
#Column(nullable = false)
public String getTitle() {
return title;
}
#Column(nullable = false)
public void setTitle(String title) {
this.title = title;
}
Note:
So in order to avoid this, you have to choose between:
Using annotations with the field.
And using them with its setter.
Spring Boot 2.0.0.M5, JPA, Hibernate 5.2.11.Final
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "auto_gen")
#SequenceGenerator(name = "auto_gen", sequenceName = "customer_id_seq", allocationSize=1)
#Column(name = "id")
private Long id;
This is a working sample:
package hello;
import org.hibernate.annotations.Type;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
#Entity
#Table(name = "customer")
public class Customer {
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "auto_gen")
#SequenceGenerator(name = "auto_gen", sequenceName = "customer_id_seq", allocationSize = 1)
#Column(name = "id")
private Long id;
#Column(name = "first_name")
//#Type(type="org.hibernate.type.StringType")
private String firstName;
#Column(name = "last_name")
//#Type(type="org.hibernate.type.StringType")
private String lastName;
protected Customer() {
}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
#Override
public String toString() {
return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName);
}
}
Here is another case of this ERROR:
21:22:15,881 ERROR [SessionFactoryImpl] Error in named query: ch.software.gvs.TroubleNotification_DeviceType.byType org.hibernate.QueryException:
could not resolve property: type of: ch.ildsoftware.gvs.TroubleNotification_DeviceType
[select d.id from ch.ildsoftware.gvs.TroubleNotification_DeviceType d where d.type = :type]
I have following setting:
queries.xml:
<named-query name="ch.ildsoftware.gvs.TroubleNotification_DeviceType.byType">
<query>
select t.id from TroubleNotification_DeviceType t where t.type = :type
</query>
</named-query>
TroubleNotification_DeviceType.java
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name = "tblgwTroubleNotification_ADSTyp")
public class TroubleNotification_DeviceType implements Serializable {
private static final long serialVersionUID = 1L;
private TroubleNotification id;
private DeviceType type;
private String createdBy;
private String createdDate;
public TroubleNotification_DeviceType()
{}
public TroubleNotification_DeviceType(TroubleNotification id, DeviceType type) {
this.id = id;
this.type = type;
}
#Id
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "IDgwTroubleNotification", nullable = false)
public TroubleNotification getId() {
return id;
}
public void setId(TroubleNotification id) {
this.id = id;
}
#Id
#Column(name = "ADSTypID", nullable = false)
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "GeraeteTypID", nullable = false)
public DeviceType getType() {
return type;
}
public void setType(DeviceType type) {
this.type = type;
}
#Column(name = "Created", nullable = false)
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
#Column(name = "CreatedDate", nullable = false)
public String getCreatedDate() {
return createdDate;
}
public void setCreatedDate(String createdDate) {
this.createdDate = createdDate;
}
}
I suspect there might be something wrong with the #Column and #JoinColumn annotation. It's just that the column-name I join with, is from a view which aliases the column name.
But maybe something else is wrong. I'm rather new to this.
snippet out of DeviceType:
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
....
#Id
#Column(name = "GeraeteTypID", nullable = false)
public Integer getId()
{
return this.id;
}
In other classes the reference would be like this, and work well (yet the column name is identical):
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "GeraeteTypID", nullable = false)
public DeviceType getType()
{
return this.type;
}
snippet out of an EJB:
#Override
#SuppressWarnings("unchecked")
public List<TroubleNotification> getTroubleNotificationByDeviceType(DeviceType aType)
{
// first get all IDgwTroubleNotification for ADSTypID
Query idSet = gvsData.createNamedQuery(
TroubleNotification_DeviceType.class.getName() + ".byType");
idSet.setParameter("type", aType);
List<TroubleNotification> idSetResult = idSet.getResultList();
final List<TroubleNotification> troubleNotificationResult = new ArrayList<TroubleNotification>();
for (int i = 0; i < idSetResult.size(); i++) {
// get all Notification for IDgwTroubleNotification
Query notificationById = gvsData.createNamedQuery(
TroubleNotification.class.getName() + ".byId");
notificationById.setParameter("id", idSetResult.get(i));
troubleNotificationResult.add((TroubleNotification) notificationById.getResultList());
}
return troubleNotificationResult;
}
Thank you for your help!
I discovered that my DB mapping was not at all proper. I have an n:m relation, which doesn't seem like an easy one with hibernate. But this was very helpful:
Hibernate Many-To-Many Revisited
But that was still not solving the problem. And I discovered that I have composite primary keys, that the primary keys of two tables are mapped in the n:m table. Another not so easy setting. So I followed this thread: Mapping ManyToMany with composite Primary key and Annotation:
The configuration from the second link, together with an SQL statement according to the second strategy in the first link works.