I make method (acceptUseroffermapping) in a REST-controller (UserOfferController) in which I want to delete record in the DB (UserOfferMapping table). But the problem is that record not deleted and relation also saved after I run this method.
I have also UserOfferMapping class which maps to User class. In UserOfferController I manipulate with UserOfferMapping: creating, selecting records from DB and also trying to delete records but have fail.
UserOfferController.java:
/*...*/
#POST
#RequestMapping("/acceptUserOfferMapping")
public void acceptUseroffermapping(#RequestBody Map<String,
String> body) throws ParseException {
String userId = body.get("userId");
String offerId = body.get("offerId");
Optional<User> user = userRepository.findById(Integer.parseInt(userId));
UserOfferMapping mapping = userOfferMappingRepository.getById(Integer.parseInt(userId));
user.get().getUserOfferMapping().remove(mapping);
userRepository.save(user.get());
userOfferMappingRepository.deleteById(Integer.parseInt(offerId));
}
/*...*/
User.java:
/*some imports*/
#Entity
#Table(name = "User")
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private int id;
/* ...
* a lot of fields
* ...
*/
// Important section which describes all Role Project and Skill mapping
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Set<UserUserrolemapping> userrolemapings = new HashSet<>();
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Set<Userprojectmapping> userprojectmappings = new HashSet<>();
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
private Set<UserOfferMapping> userOfferMapping = new HashSet<>();
#OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
#OrderBy
private Set<Userskillmapping> userskillmappings = new HashSet<>();
/* ...
* a lot of fields too
* ...
*/
/* getter and setters */
}
UserOfferMappingRepository.java:
public interface UserOfferMappingRepository extends JpaRepository<UserOfferMapping, Integer> {
public List<UserOfferMapping> getAllByUser(Optional<User> user);
public UserOfferMapping getUserOfferMappingByUserAndProjectAndUserRole(User user, Userproject userproject, Userrole userrole);
public UserOfferMapping getById(int id);
public void deleteById(int id);
}
UserOfferMapping.java:
#Entity
public class UserOfferMapping {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#ManyToOne
#JoinColumn(name = "userid")
#JsonBackReference
private User user;
#ManyToOne
#JoinColumn(name = "roleid")
private Userrole userRole;
#ManyToOne
#JoinColumn(name = "projectid")
private Userproject project;
#Column(name = "fromdate", nullable = true)
private Date fromdate;
#Column(name = "todate", nullable = true)
private Date todate;
#Column(name = "chance")
private int chance;
#Column(name = "percent")
private int percent;
public int getId() {
return id;
}
public User getUser() {
return user;
}
public Userrole getUserRole() {
return userRole;
}
public Userproject getProject() {
return project;
}
public Date getFromdate() {
return fromdate;
}
public int getChance() {
return chance;
}
public int getPercent() {
return percent;
}
public void setId(int id) {
this.id = id;
}
public void setUser(User user) {
this.user = user;
}
public void setUserRole(Userrole userRole) {
this.userRole = userRole;
}
public void setProject(Userproject project) {
this.project = project;
}
public void setFromdate(Date fromdate) {
this.fromdate = fromdate;
}
public void setChance(int chance) {
this.chance = chance;
}
public void setPercent(int percent) {
this.percent = percent;
}
public void setTodate(Date todate) {
this.todate = todate;
}
public Date getTodate() {
return todate;
}
}
Can you try to use this
public interface UserOfferMappingRepository extends JpaRepository<UserOfferMapping, Integer> {
public List<UserOfferMapping> getAllByUser(Optional<User> user);
public UserOfferMapping getUserOfferMappingByUserAndProjectAndUserRole(User user, Userproject userproject, Userrole userrole);
public UserOfferMapping getById(int id);
// public void deleteById(int id);
#Modifying(clearAutomatically = true)
#Query(value = "Delete from UserOfferMapping c WHERE c.id=:id")
public void deleteById(#Param("id") int id);
}
So, you have bidirectional entity association.
Try to add mapping.setUser(null); before userRepository.save.
Persisting and deleting objects requires a transaction in JPA so that is why you have to define #Transactional annotation before the method in Repository for example `
#Transactional
public void deleteById(#Param("id") int id);
Related
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);
}
}
So I have a one to many and many to one relation between two classes. When I try to update an entity, the parent is updated and child throws an error. In that case I expect the parent update to be rolled back but it is not. Since I have a one to many relation, an update on the parent is expected to insert a child but when the child throws an error shouldnt the parent's update be rolled back? If it is of any relation the child's error is thrown due to the unique constraints on the child/account entity.
Below are my two models:
/** User model **/
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false)
private int id;
#Column(name = "type")
private String type;
#Column(name = "username", nullable = false)
private String username;
...
// define one to many relation between User and Account
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#JoinColumn(name = "user_id")
private Set<Account> accounts;
public User() {
}
#PrePersist
void preInsert() throws ParseException {
...
}
// field getters and setters
...
// returns Account list associated with User
public Set<Account> getAccount() {
return accounts;
}
// set Account list associated with User
public void setAccount(Set<Account> accounts) {
this.accounts = accounts;
}
}
Model 2:
/** Account model **/
#Entity
#Table(name = "account", uniqueConstraints =
#UniqueConstraint(columnNames = {"user_id", "entity_id", "branch_id", "type"}))
public class Account {
private int id;
#Column(name = "user_id", nullable = false)
private int user_id;
...
private User user;
// constructor
public Account() {
}
#PrePersist
void preInsert() throws ParseException {
...
}
// field getters and setters
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", nullable = false)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
...
// define many to one relation between Account and User
// get User associated with Account
#ManyToOne
#JoinColumn(name = "user_id", insertable = false, updatable = false)
public User getUser() {
return user;
}
// set User associated with Account
public void setUser(User user) {
this.user = user;
}
}
UserDAO:
#Repository("userDao")
#Transactional(propagation = Propagation.REQUIRED)
public class UserDAO {
#PersistenceContext
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public void insert(User user) {
entityManager.persist(user);
}
public void update(User user) {
entityManager.merge(user);
}
....
}
User service (where i am calling the update)
#Service
public class UserService {
private UserDAO userDAO;
public UserDAO getUserDao() {
return userDAO;
}
#Autowired
public void setUserDao(UserDAO userDAO) {
this.userDAO = userDAO;
}
public boolean addUser(SignupComponent signupComponent) {
....
else {
// case (4)
// get user object
User userObj = getUserDao().findUser(user.getPhone());
// update user object, adding account and account details
Set<Account> accounts = userObj.getAccount();
Account a = new Account();
a.setBranch_id(signupComponent.branch_id);
a.setEntity_id(signupComponent.entity_id);
if (signupComponent.type != -1) {
a.setType(signupComponent.type);
}
a.setUser(userObj);
userObj.setAccount(accounts);
userObj.setEmail(signupComponent.user.getEmail());
AccountDetails ad = new AccountDetails(); //never mind this line, i have another one to one relation with another entity
ad.setAccount(a);
a.setAccountDetails(ad);
accounts.add(a);
try {
getUserDao().update(userObj);
return true;
}
catch(Exception e) {
signupComponent.error = e.toString();
return false;
}
}
}
}
You are defining JoinColumn at both the sides.You need to define at one side. How would it store an arbitrary number of foreign keys in a single row? Instead, it must let the tables of the entities in the collection have foreign keys back to the source entity table.
Try this:
public class User{
#OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL,mappedBy="user")
private Set<Account> accounts;
}
User class
/** User model **/
#Entity
#Table(name = "user")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", unique = true, nullable = false)
private int id;
#Column(name = "type")
private String type;
#Column(name = "username", nullable = false)
private String username;
...
// FetchType should be Lazy to improve performance
#OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL,mappedBy="user")
private Set<Account> accounts;
//mappedBy says that this side is inverse side of relation and source is user which is mapped by user field name in Account class
public User() {
}
#PrePersist
void preInsert() throws ParseException {
...
}
// field getters and setters
...
// returns Account list associated with User
public Set<Account> getAccount() {
return accounts;
}
// set Account list associated with User
public void setAccount(Set<Account> accounts) {
this.accounts = accounts;
}
}
Account class
/** Account model **/
#Entity
#Table(name = "account", uniqueConstraints =
#UniqueConstraint(columnNames = {"user_id", "entity_id", "branch_id", "type"}))
public class Account {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", nullable = false)
private int id;
#Column(name = "user_id", nullable = false)
private int user_id;
...
#ManyToOne(cascade=CascadeType.ALL)
#JoinColumn(name = "user_id", insertable = false, updatable = false)
private User user;
// constructor
public Account() {
}
#PrePersist
void preInsert() throws ParseException {
...
}
// field getters and setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
...
// define many to one relation between Account and User
// get User associated with Account
public User getUser() {
return user;
}
// set User associated with Account
public void setUser(User user) {
this.user = user;
}
}
See now, when you save User then Account class will not be updated as User is at inverse side. But when you save Account class then user_id which is present in account table will get update as it is source side of relation.
I'm trying to implement to following : Many to Many Hibernate Mapping for additional property in the join table
for creating many to many connection with extra fields. I keep getting this exception:
org.hibernate.MappingException: Repeated column in mapping for entity:
UserRole column: id (should be mapped with insert="false" update="false")
Why?
I'm using spring 4 and MySQL
My code:
#Entity
#AssociationOverrides({ #AssociationOverride(name = "pk.user", joinColumns = #JoinColumn(name = "id")),
#AssociationOverride(name = "pk.role", joinColumns = #JoinColumn(name = "id")) })
public class UserRole extends AbstractEntity {
private UserRoleId pk;
public UserRole(User user, Role role) {
super();
this.pk = new UserRoleId(user, role);
}
#EmbeddedId
public UserRoleId getPk() {
return pk;
}
public Long getUserId() {
return pk.getUser().getId();
}
public Long getRoleId() {
return pk.getRole().getId();
}
}
#Embeddable
public class UserRoleId implements Serializable {
private User user;
private Role role;
public UserRoleId(User user, Role role) {
super();
this.user = user;
this.role = role;
}
#ManyToOne
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
#ManyToOne
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
}
#MappedSuperclass
public abstract class AbstractEntity {
#Column(nullable = false)
protected Date timeCreated;
#Column
private Long modifiedBy;
public AbstractEntity() {
super();
this.timeCreated = DateUtil.now();
this.modifiedBy = 0l;
}
public Date getTimeCreated() {
return timeCreated;
}
public void setTimeCreated(Date timeCreated) {
this.timeCreated = timeCreated;
}
#Override
public abstract String toString();
}
You can't define same column as more than times. If two columns present there, You need to mention insert = "false" and update = "false"
#Entity
#AssociationOverrides({ #AssociationOverride(name = "pk.user", joinColumns = #JoinColumn(name = "id")),
#AssociationOverride(name = "pk.role", joinColumns = #JoinColumn(name = "id", insertable = false, updatable = false)) })
public class UserRole extends AbstractEntity {
private UserRoleId pk;
public UserRole(User user, Role role) {
super();
this.pk = new UserRoleId(user, role);
}
#EmbeddedId
public UserRoleId getPk() {
return pk;
}
public Long getUserId() {
return pk.getUser().getId();
}
public Long getRoleId() {
return pk.getRole().getId();
}
}
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.
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 :)