hibernate h2 not generating relations - java

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

Related

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);
}
}

Update Associated entity on updatign foreign key - Hibernate

I have a mysql table which maintains data of drivers and maintains the city of the driver by using the foreign key mapping.
public class Drivers {
private Integer currentCityId;
private Integer id;
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "current_city_id")
public Integer getCurrentCityId() {
return currentCityId;
}
public void setCurrentCityId(Integer currentCityId) {
this.currentCityId = currentCityId;
}
#ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
#JoinColumn(name = "current_city_id", insertable = false, updatable = false, nullable = true, unique = false)
public Cities getCities() {
return cities;
}
public void setCities(Cities cities) {
this.cities = cities;
}
}
#Entity
#Table(name = "cities", catalog = "mytable_production", uniqueConstraints = #UniqueConstraint(columnNames = "name"))
public class Cities implements java.io.Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String name;
private String aliasName1;
private String aliasName2;
private int stateId;
}
Now, I am updating the city of the driver by updating the foreignKey value in the table using
#Transactional
public void updateCityBizLogic(int driverId,int newCityId) {
//Some biz logic
Drivers d = driversDao.updateCity(driverId,newCityId);
log.info("Updated driverCity to {}",d.getCities.getName());
}
public class DriversDao {
#Transactional
public Drivers updateCity(int DriverId, int newCityId) {
Criteria criteria = sessionFactory.getCurrentSession().createCriteria(Drivers.class);
criteria.add(Restrictions.eq("id", Integer.parseInt(id)));
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
Drivers d = criteria.list().get(0);
d.setCurrentCityId(newCityId);
session.update(d);
return d;
}
}
But in the log line, it is printing the old city name. I want the session to update the associated entities when I update any of the foreign key ( like update the joined cities object, when I update the cityId)
Can someone point out what I am missing here and achieve it?

How to fix org.hibernate.MappingException?

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.

Hibernate mapping in Java: org.hibernate.MappingException: Repeated column in mapping for entity

I try to gather statistics of visitors for two services. It consists of daily visitors statistics and overall record. Each service can be accessed by different names. For example, user, admin, support etc. Each will have its own record as own statistics.
Here is my DB structure:
service_one: id, name
service_two: id, name
daily_stats: id, date, service_one_id, service_one_visitors,
service_two_id, service_two_visitors, overall_visitors
record_stats: id, service_one_id, service_one_record,
service_one_record_date, service_two_id, service_two_record,
service_two_record_date
Here are the relations between tables:
service_one --- (one to many) ---> daily_stats(service_one_id)
service_one --- (one to many) ---> record_stats(service_one_id)
service_two --- (one to many) ---> daily_stats(service_two_id)
service_two --- (one to many) ---> record_stats(service_two_id)
Mapping for service_one (the same is for service_two). Also setters were omitted in order to shorten the example:
#Entity
#Table(name = "service_one")
public class ServiceOne implements Serializable {
private int id;
private String name;
private Set<RecordStats> recordStats = new HashSet<RecordStats>(0);
private Set<DailyStats> dailyStats = new HashSet<DailyStats>(0);
public ServiceOne() {}
public ServiceOne(int id, String name) {
this.id = id;
this.name = name;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", nullable = false, unique = true)
public int getId() {
return id;
}
#Column(name = "name")
public String getName() {
return name;
}
#OneToMany(fetch = LAZY, mappedBy = "service_one_id")
public Set<RecordStats> getRecordStats() {
return recordStats;
}
#OneToMany(fetch = LAZY, mappedBy = "service_one_id")
public Set<DailyStats> getDailyStats() {
return dailyStats;
}
}
daily_stats mapping:
#Entity
#Table(name = "daily_stats", uniqueConstraints = {
#UniqueConstraint(columnNames = "date")
})
public class DailyStats implements Serializable{
private int id;
private Date date;
private ServiceOne service_one_id;
private int service_one_visitors;
private ServiceTwo service_two_id;
private int service_two_visitors;
private int overall_visitors;
public DailyStats() {}
public DailyStats(DailyStats rec) {
this.id = rec.getId();
//...
}
#Id
#GeneratedValue
#Column(name = "id", nullable = false)
public int getId() {
return id;
}
#Temporal(DATE)
#Column(name = "date")
public Date getDate() {
return date;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
#Column(name = "service_one_visitors")
public int getService_one_visitors() {
return service_one_visitors;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceTwo getService_two_id() {
return service_two_id;
}
#Column(name = "service_two_visitors")
public int getService_two_visitors() {
return service_two_visitors;
}
#Column(name = "overall_visitors")
public int getOverall_visitors() {
return overall_visitors;
}
}
record_stats mapping:
#Entity
#Table(name = "record_stats", uniqueConstraints = {
#UniqueConstraint(columnNames = "service_one_record_date"),
#UniqueConstraint(columnNames = "service_two_record_date")
})
public class RecordStats implements Serializable {
private int id;
private ServiceOne service_one_id;
private int service_one_record;
private Date service_one_rec_date;
private ServiceTwo service_two_id;
private int service_two_record;
private Date service_two_rec_date;
public RecordStats() {}
public RecordStats(RecordStats rec) {
this.id = rec.getId();
//...
}
#Id
#GeneratedValue
#Column(name = "id", nullable = false)
public int getId() {
return id;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
#Column(name = "service_one_record")
public int getService_one_record() {
return service_one_record;
}
#Column(name = "service_one_record_date")
#Temporal(DATE)
public Date getService_one_rec_date() {
return service_one_rec_date;
}
#ManyToOne(fetch = LAZY)
#JoinColumn(name = "id", nullable = false)
public ServiceTwo getService_two_id() {
return service_two_id;
}
#Column(name = "service_two_record")
public int getService_two_record() {
return service_two_record;
}
#Column(name = "service_two_record_date")
#Temporal(DATE)
public Date getService_two_rec_date() {
return service_two_rec_date;
}
}
Trying to create new entry throws exception:
public static void main(String[] args) {
ServiceOne serviceOne = new ServiceOne();
serviceOne.setName("test");
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(serviceOne);
session.getTransaction().commit();
//get records
session = sessionFactory.openSession();
session.beginTransaction();
List result = session.createQuery("from service_one").list();
for (ServiceOne o : (List<ServiceOne>)result) {
System.out.println(o.getName());
}
session.getTransaction().commit();
session.close();
}
org.hibernate.MappingException: Repeated column in mapping for entity:
VisitorsCounter.model.entity.DailyStats column: id (should be
mapped with insert="false" update="false")
What is wrong with my mapping?
It seems to me that
#JoinColumn(name = "id", nullable = false)
public ServiceOne getService_one_id() {
return service_one_id;
}
in DailyStats is wrong; you should have name = "service_one_id".
You have the same problem in getService_two_id() and in methods of same names in RecordStats.
May I also ask why don't you name the references in the classes fields serviceOne and serviceTwo instead of service_one_id and service_two_id.

Hibernate many-to-many withe extracolumn criteria problems

I followed this tutorial to implement in my domain model a many-to-many relationship with an extra column. It works great but I'm unable to create a criteria to query a field within the left side of my relation.
Taking this code
#Entity
#Table( name = "projects")
public class Project implements Cloneable, Serializable{
private Long id;
private String name;
private Set<ProjectOrganization> projectOrganizations = new HashSet<ProjectOrganization>(0);
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false)
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "name", length = 255, nullable = false)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.project")
#Cascade(value = { CascadeType.ALL })
public Set<ProjectOrganization> getProjectOrganizations() {
return this.projectOrganizations;
}
public void setProjectOrganizations(Set<ProjectOrganization> organizationProjects) {
this.projectOrganizations = organizationProjects;
}
}
#Entity
#Table(name = "projects_has_organizations")
#AssociationOverrides({ #AssociationOverride(name = "pk.project", joinColumns = #JoinColumn(name = "projects_id")),
#AssociationOverride(name = "pk.organization", joinColumns = #JoinColumn(name = "organizations_id"))
})
public class ProjectOrganization implements Cloneable, Serializable {
private ProjectOrganizationPK pk = new ProjectOrganizationPK();
private OrganizationRolesEnum role;
public ProjectOrganization() {
}
#Transient
public Organization getOrganization() {
return getPk().getOrganization();
}
public void setOrganization(Organization organization) {
getPk().setOrganization(organization);
}
#EmbeddedId
public ProjectOrganizationPK getPk() {
return pk;
}
public void setPk(ProjectOrganizationPK pk) {
this.pk = pk;
}
#Transient
public Project getProject() {
return getPk().getProject();
}
public void setProject(Project project) {
getPk().setProject(project);
}
#Enumerated(EnumType.STRING)
#Column(nullable = false, length = 50)
public OrganizationRolesEnum getRole() {
return role;
}
public void setRole(OrganizationRolesEnum role) {
this.role = role;
}
}
#Embeddable
public class ProjectOrganizationPK implements Cloneable, Serializable {
/** Generated serial version UID */
private static final long serialVersionUID = -4534322563105003365L;
private Organization organization;
private Project project;
#ManyToOne
public Organization getOrganization() {
return organization;
}
public void setOrganization(Organization organization) {
this.organization = organization;
}
#ManyToOne
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
}
#Entity
#Table(name = "organizations")
public class Organization implements Cloneable, Serializable {
private Long id;
private String name;
private Set<ProjectOrganization> projectOrganizations = new HashSet<ProjectOrganization>(0);
public Organization() {
}
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false)
#Override
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
#Column(name = "name", nullable = false, length = 255)
#NotNull(message = "A name is required!")
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
#OneToMany(fetch = FetchType.EAGER, mappedBy = "pk.organization")
public Set<ProjectOrganization> getProjectOrganization() {
return this.projectOrganizations;
}
public void setProjectOrganization(Set<ProjectOrganization> projectOrganizations) {
this.projectOrganizations = projectOrganizations;
}
}
I want is to create a criteria to select a Project which has an organization with a requested name.
final Criteria crit = getSession().createCriteria(Project.class);
crit.createCriteria("projectOrganizations", "projectOrganization").
createAlias("pk.organization", "organization").
add( Restrictions.like("organization.name", "TEST"));
But when i run this code i have this error
2012-10-19 10:38:43,095 ERROR [org.hibernate.util.JDBCExceptionReporter] Unknown column 'organizati2_.name' in 'where clause'
and the sql query generated by hibernate is incomplete, doesn't join projects_has_organizations.organization with organization.id.. So it can't find column organization.name
SELECT
....
FROM
projects this_
INNER JOIN projects_has_organizations projectorg1_ ON this_.id = projectorg1_.projects_id
WHERE
projectorg1_.role =?
AND organizati2_. NAME LIKE ?
ORDER BY
this_.publish_date DESC
What's wrong with this code? How can i build query using criteria ?
I suspect that the problem is due to lazy fetching, try explicitly telling hibernate to eagerly fetch the property you need. This is done with the method
.setFetchMode("propertyName", FetchMode.EAGER)
So, in otherwords, try eagerly fetch the organisation property :)

Categories

Resources