How to fix org.hibernate.MappingException? - java

I'm new to JPA and getting this error when trying to set UserContact Entity.
Caused by: org.hibernate.MappingException: Could not determine type for: java.util.Set, at table: USER_ID, for columns: [org.hibernate.mapping.Column(userContact)]
I have 2 Entity Classes and one #Embeddable class for composite key. There seems to be many solutions to this problem so I've mixed and matched attributes along getters/setters and fields. I've tried #JsonBackReference and #JsonManagedReference, #ElementCollection and other annotations. Using #Access(AccessType.PROPERTY) did start the server correctly but gave me this error when trying to perform db operation.
org.codehaus.jackson.map.JsonMappingException: failed to lazily initialize a collection of role:
Any help would be appreciated. Here are my Entities.
User
#Entity
#Table(name = "USER_RECORD")
public class User {
private UserRecordId id;
private String name;
private String address;
#Column
#ElementCollection(targetClass=UserContact.class)
private Set<UserContact> userContact = new HashSet<UserContact>(0);
#EmbeddedId
#AttributeOverrides({
#AttributeOverride(name = "userId", column = #Column(name = "USER_ID", nullable = false)),
#AttributeOverride(name = "userId2", column = #Column(name = "USER_ID2", nullable = false)) })
public UserRecordId getId() {
return this.id;
}
public void setId(UserRecordId id) {
this.id = id;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
public Set<UserContact> getUserContact() {
return this.userContact;
}
public void setUserContact(Set<UserContact> userContact) {
this.userContact = userContact;
}
#Column(name = "USER_NAME", nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "USER_ADDRESS", nullable = false)
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
UserContact
#Entity
#Table(name = "USER_CONTACT")
public class UserContact {
private String userContactId;
private String name;
private String country;
private User user;
#Id
#Column(name = "USER_CONTACT_ID", unique = true, nullable = false)
public String getUserContactId() {
return this.userContactId;
}
public void setUserContactId(String userContactId) {
this.userContactId = userContactId;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumns({
#JoinColumn(name = "USER_ID", referencedColumnName = "USER_ID"),
#JoinColumn(name = "USER_ID2", referencedColumnName = "USER_ID2") })
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
#Column(name = "CONTACT_NAME", nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#Column(name = "CONTACT_COUNTRY", nullable = false)
public String getCountry() {
return this.country;
}
public void setCountry(String country) {
this.country = country;
}
UserRecordId/Embeddable
#Embeddable
public class UserRecordId
private String userId;
private String userId2;
#Column(name = "USER_ID", nullable = false)
public String getUserId() {
return this.userId;
}
.../////getUserid2
......
.....
override equals & hash code

You seem to have annotated a field AND a getter (userContact). You should use either FIELD or PROPERTY access but not both (particularly for the same field!).
Also you have annotated it once as ElementCollection and once as OneToMany. Can't be both, and certainly can't be ElementCollection when the element is an Entity.

Related

Spring boot lazy loaded entity not loading all properties

I have a Spring Boot 2.1.13 (Java 8) project with MySQL 8.0.21 and mysql-connector-java version: 8.0.22 with the following classes.
#Entity
#Table(name = "user")
#JsonIgnoreProperties({"type", "location", "hibernateLazyInitializer", "handler"})
public class User implements java.io.Serializable {
private UserType userType;
private Location location;
private long id;
private String name;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "usertypeid")
public UserType getUserType() {
return this.userType;
}
public void setUserType(UserType userType) {
this.userType = userType;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "locationid", nullable = false)
public Location getLocation() {
return this.location;
}
public void setLocation(Location location) {
this.location = location;
}
#Column(name = "name", nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
#Entity
#Table(name = "usertype")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class UserType implements java.io.Serializable {
private long id;
private String name;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "name", nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
#Entity
#Table(name = "location")
public class Location implements java.io.Serializable {
private long id;
private String name;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
#Column(name = "name", nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
I fetch the user record using the following code
User user = userRepository.findById(userId).orElse(null);
Now when I try to fetch the UserType object from my user object, I don't get any values, except the ID. For example, when I run the following command, it gives me a null value
user.getUserType().getName()
However, when I run the following code, I get the expected not null value.
user.getLocation().getName()
Both userType and location are lazy-loaded, however, the values of only location are available in the code.
I have checked the values in DB tables. They are not null for both user type and location.
I have checked the values in the debugger as well. The Location object seems to be a proxy, however, the UserType not a hibernate proxy object. I am not sure if this is an issue.

Child entity elements not persisting in one to many mapping with hibernate and spring data jpa

I have used spring boot with hibernate. And swagger to generate the dtos and the api interface.
There are two entities. The project entity is the parent and application entity is the child. Have create a onetomany relationship. But when i try to persist. I see not applications getting added for a project.
Project Entity:
#Entity
#Table(name="ProjectEntity")
public class ProjectEntity {
#Id
#Column(name = "ProjectGuid", length = 36, nullable = false, unique = true)
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(name = "Name")
private String name;
#OneToMany(mappedBy="projectApp", cascade = CascadeType.ALL)
private List<ApplicationEntity> apps=new ArrayList<>();
public ProjectEntity() {
}
public ProjectEntity(Long id, String name) {
this.id = id;
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ApplicationEntity> getApps() {
return apps;
}
public void setApps(List<ApplicationEntity> apps) {
this.apps = apps;
}
}
Application Entity:
#Entity
#Table(name="ApplicationEntity")
public class ApplicationEntity {
#Id
#Column(name = "Name", length = 36, nullable = false, unique = true)
private String name;
private String repositoryUrl;
#ManyToOne
#Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
#JoinColumn(name = "ProjectGuid")
private ProjectEntity projectApp;
public ApplicationEntity() {
}
public ApplicationEntity(String name, String repositoryUrl) {
this.name = name;
this.repositoryUrl = repositoryUrl;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRepositoryUrl() {
return repositoryUrl;
}
public void setRepositoryUrl(String repositoryUrl) {
this.repositoryUrl = repositoryUrl;
}
public ProjectEntity getProjectApp() {
return projectApp;
}
public void setProjectApp(ProjectEntity projectApp) {
this.projectApp = projectApp;
}
}
Controller operation:
ProjectEntity project = projectService.getProject(projectName);
List<ApplicationEntity> appList = new ArrayList<>();
ApplicationEntity appEntity = new ApplicationEntity(app.getName(), app.getRepositoryUrl());
applicationRepository.save(appEntity);
appList.add(appEntity);
project.setApps(appList);
projectRepository.save(project);
You need to set the id of the ProjectEntity on the owning side (which is the ApplicationEntity)
appEntity.setProjectApp(project);
Otherwise hibernate (and your database) does not know to which parent a ApplicationEntity belongs.
Here is an example many to one relation with spring data jpa :
#Data
#MappedSuperclass
public class BaseEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
}
#Data
#Entity
public class Question extends BaseEntity{
private String questionText;
private int anketId;
private int subjectId;
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "question")
List<Answer> answers;
}
#Data
#Entity
public class Answer extends BaseEntity{
private String answerText;
private String code;
private int score;
private int priority;
private boolean isValidAnswer;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "question_id", referencedColumnName = "id", insertable = false, updatable = false)
private Question question;
}
#DataJpaTest
public class QuestionRepositoryTest {
#Autowired
TestEntityManager entityManager;
#Autowired
QuestionRepository sut;
#Test
public void it_should_create_question_wiht_answers() {
Question question = new Question();
question.setSubjectId(1);
question.setAnketId(1);
question.setQuestionText("test question");
Answer answer = new Answer();
answer.setAnswerText("answer");
answer.setCode("1a");
answer.setPriority(0);
answer.setValidAnswer(true);
question.setAnswers(Arrays.asList(answer));
entityManager.persistAndFlush(question);
List<Question> questionList = sut.findAll();
assertThat(questionList).containsExactly(question);
assertThat(questionList.get(0).getAnswers().size()).isGreaterThan(0);
}
}

Hibernate #ManyToMany relationship with composite keys that share a property

So I am working with a database that uses a lot of composite keys. I am trying to use JPA/hibernate to set up an JoinTable for one of the relationships. Here is a trimmed down example of what is being done
Parent Class
#Entity
#Table(name = "PROTAGONIST")
public class Protagonist {
private Integer id;
private String name;
#Id
#Column(name = "id", nullable = false)
public Integer getId() {return id;}
public void setId(Integer id) { this.id = id;}
#Column(name = "pro_name", nullable = false, length = 50)
public String getName() {return name;}
public void setName(String name) { this.name = name;}
}
Item ID Class
#Embeddable
public class ItemId {
private int pId;
private short invSlot;
#Column(name = "P_Id", nullable = false)
public int getpId() {return pId;}
public void setpId(int pId) { this.pId = pId;}
#Column(name = "Inv_SlotNum", nullable = false)
public short getInvSlot() {return invSlot;}
public void setInvSlot(short invSlot) { this.invSlot = invSlot;}
}
Item Class
public class Item {
private ItemId id;
private String itemName;
private Double cost;
private Set<Buff> buffs;
#EmbeddedId
public ItemId getId() {return id;}
public void setId(ItemId id) { this.id = id;}
#Column(name = "Item_Name", nullable = false, length = 100)
public String getItemName() {return itemName;}
public void setItemName(String name) { this.itemName = name;}
#Column(name = "Item_Cost")
public Double getCost() {return cost;}
public void setCost(Double cost) { this.cost = cost;}
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "BUFFSONITEMS",
joinColumns = {
#JoinColumn(name = "P_Id", referencedColumnName = "P_Id"),
#JoinColumn(name = "Inv_SlotNum", referencedColumnName = "Inv_SlotNum")
},
inverseJoinColumns = {
#JoinColumn(name = "P_Id", referencedColumnName = "P_Id"),
#JoinColumn(name = "Buff_SlotNum", referencedColumnName = "Buff_SlotNum")
}
)
public Set<Buff> getBuffs() {return buffs;}
public void setBuffs(Set<Buff> buffs) { this.buffs = buffs;}
}
Buff ID Class
#Embeddable
public class BuffId {
private Integer pId;
private Short buffSlotNum;
#Column(name = "P_Id", nullable = false)
public Integer getpId() {return pId;}
public void setpId(Integer pId) { this.pId = pId;}
#Column(name = "Buff_SlotNum", nullable = false)
public Short getBuffSlotNum() {return buffSlotNum;}
public void setBuffSlotNum(Short buffSeqNum) { this.buffSlotNum = buffSeqNum;}
}
Buff Class
#Entity
#Table(name = "BUFF")
public class Buff {
private BuffId id;
private String buffName;
private Long duration;
private Set<Item> buffedItems;
#EmbeddedId
public BuffId getId() {return id;}
public void setId(BuffId id) { this.id = id;}
#Column(name = "Buff_Name", nullable = false, length = 100)
public String getBuffName() {return buffName;}
public void setBuffName(String name) { this.buffName = name;}
#Column(name = "Duration", nullable = false)
public Long getDuration() {return duration;}
public void setDuration(Long duration) { this.duration = duration;}
#ManyToMany(fetch = FetchType.LAZY)
#JoinTable(name = "BUFFSONITEMS",
joinColumns = {
#JoinColumn(name = "P_Id", referencedColumnName = "P_Id"),
#JoinColumn(name = "Buff_SlotNum", referencedColumnName = "Buff_SlotNum")
},
inverseJoinColumns = {
#JoinColumn(name = "P_Id", referencedColumnName = "P_Id"),
#JoinColumn(name = "Inv_SlotNum", referencedColumnName = "Inv_SlotNum")
}
)
public Set<Item> getBuffedItems() {return buffedItems;}
public void setBuffedItems(Set<Item> buffedItems) { this.buffedItems = buffedItems;}
}
Whenever I attempt to start Spring Boot I get the following exception org.hibernate.MappingException: Repeated column in mapping for collection: com.blankd.composite.key.Item.buffs column: P_Id. The BUFFSONITEMS table uses all 3 columns as part of the primary key for each row in that table. All three columns also have forgein key constraints on the respective tables. This means that P_Id has a forgein key constraint on both Buff and Item.
I am not sure what I am doing wrong as I need the P_Id in order to uniquely identify the row in each table.
You have to choose one side of the many-to-many relationship to be the "owning" side. The "inverse" side must then use the mappedBy element.
If you were to choose Item.buffs to be the owning side, you would map Buff.buffedItems like this:
#ManyToMany(mappedBy="buffs")
public Set<Item> getBuffedItems() {return buffedItems;}

Hibernate #Many to many grouped map mapping

I would like to sovle this problec, cause it's looks interesting, to get grouped objects directly from box
I have db sheme about this:
Teacher
-id
-name
Group
-id
-name
Subject
-id
-name
Several teachers can teaches one subject
Subject_teachers
-subject_id
-teacher_id
Group_subjects
-group_id
-subject_id
I would to get grouped lessons by groups for teacher
class Teacher{
#Id id ,
...
#ManyToMany
???
Map<Group,Subject) subjects;
};
#Entity
#Table(name = "Teacher")
public class Teacher {
private Integer teacherId;
private String name;
private Set<SubjectTeachers> subjectTeachers = new HashSet<SubjectTeachers>(0);
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "teacher_id", unique = true, nullable = false)
public Integer getTeacherId() {
return teacherId;
}
public void setTeacherId(Integer teacherId) {
this.teacherId = teacherId;
}
#Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setTitle(String name) {
this.name = name;
}
#OneToMany(mappedBy = "subjectTeachers", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
public Set<SubjectTeachers> getSubjectTeachers() {
return subjectTeachers;
}
public void setProjectTags(Set<SubjectTeachers> subjectTeachers) {
this.subjectTeachers = subjectTeachers;
}
}
#Entity
#Table(name = "Subject")
public class Subject{
private Integer subjectId;
private String name;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "subject_id", unique = true, nullable = false)
public Integer getSubjectId() {
return subjectId;
}
public void setSubjectId(Integer subjectId) {
this.subjectId = subjectId;
}
#Column(name = "name", nullable = false)
public String getName() {
return name;
}
public void setTitle(String name) {
this.name = name;
}
}
#Entity
#Table(name ="subject_teachers")
public SubjectTeachers{
private Integer subjectTeachersID;
private Teacher teacher;
private Subject subject;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "subjectTeachersID", unique = true, nullable = false)
public Integer getSubjectTeachersId() {
return subjectTeachersID;
}
public void setSubjectTeachersId(Integer subjectTeachersID) {
this.subjectTeachersID = subjectTeachersID;
}
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "teacher_id", nullable = false)
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
#OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "subject_id", nullable = false)
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
}
#Entity
#Table(name = "group_subjects")
public class GroupSubjects{
private Integer groupId;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "group_id", unique = true, nullable = false)
public Integer getGroupId() {
return groupId;
}
public void setGroupId(Integer groupId) {
this.groupId = groupId;
}
private Subject subject;
#ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
#JoinColumn(name = "subject_id", nullable = false)
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
}
Hope its help to you..

hibernate h2 not generating relations

I'm trying to generate Hibernate mapping to my H2 database.
I have 2 tables for test, called users and users_groups.
They look like:
users table:
user_id integer PK
login varchar
password varchar
user_group_id integer FK
users_groups
user_group_id integer PK
name varchar
And the problem is that hibernate generate entities like that:
#Entity
public class Users {
private int userId;
private int userGroupId;
#Id
#Column(name = "USER_ID", nullable = false)
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
#Basic
#Column(name = "USER_GROUP_ID", nullable = false)
public int getUserGroupId() {
return userGroupId;
}
public void setUserGroupId(int userGroupId) {
this.userGroupId = userGroupId;
}
#Entity
#Table(name = "USERS_GROUPS", schema = "PUBLIC", catalog = "DATABASE")
public class UsersGroups {
private int userGroupId;
#Id
#Column(name = "USER_GROUP_ID", nullable = false)
public int getUserGroupId() {
return userGroupId;
}
public void setUserGroupId(int userGroupId) {
this.userGroupId = userGroupId;
}
So no relation annotations are generated, like #OneToMany or #ManyToMany etc. What am I doing wrong? Thanks for your help.
p.s. I want it to generate mapping like
Users class with field of UserGroup type
If the classes were auto generated like this check your relation in the database between the two tables and make sure you choose the right schema your mapping is completely wrong the for example :-
1-the auto generated classes your mapping are missing some columns, class User doesn't contain password and login columns and class UsersGroups doesn't contain name column.
2- class User doesn't have #table annotation
They should look something like this :-
Class UserGroups
#Entity
#Table(name = "USERS_GROUPS", schema = "PUBLIC", catalog = "DATABASE")
public class UsersGroups implements java.io.Serializable {
private int userGroupId;
private String name;
private Set<Users> users = new HashSet<Users>(0);
public UsersGroups() {
}
#Id
#GeneratedValue(strategy = IDENTITY) //this to make the id auto increment
#Column(name = "user_group_id", nullable = false)
public int getUserGroupId() {
return userGroupId;
}
public void setUserGroupId(int userGroupId) {
this.userGroupId = userGroupId;
}
// if name column is not unique / nullable remove values from annotation
#Column(name = "name", unique = true, nullable = false, length = 10)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name= name;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "users_groups")
public Set<Users> getUsers() {
return this.users;
}
public void setUsers(Set<Users> users) {
this.users= users;
}
}
Class Users
#Entity
#Table(name = "users", schema ="PUBLIC" , catalog ="DATABASE")
public class Users implements java.io.Serializable {
private Integer userId;
private UsersGroups usersGroups;
private String password;
private String login;
public Users() {
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "user_id", unique = true, nullable = false)
public Integer getUserId() {
return this.userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "user_group_id", nullable = false)
public UsersGroups getUsersGroups() {
return this.usersGroups;
}
public void setUsersGroups(UsersGroups usersGroups) {
this.usersGroups = usersGroups;
}
#Column(name = "password",length = 10)
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
#Column(name = "login",length = 10)
public String getLogin() {
return this.login;
}
public void setLogin(String login) {
this.login = login;
}
}
Check this full example for one to many mapping

Categories

Resources