Spring hibernate criteria nested object - hibernate-criteria

I have problem with correct query for my data.
#Id
#GeneratedValue
private Integer id;
#Size(min = 1, message = "")
#Column(unique = true)
#UniqueUserName(message = "")
private String name;
#Size(min = 1, message = "")
#Email
private String email;
#Size(min = 5, message = "")
private String password;
private boolean enabled;
#ManyToMany
#JoinTable
private List<Role> roles;
#OneToOne
#JoinColumn
private PersonalData personalData;
#OneToMany(cascade = CascadeType.REMOVE)
#JoinColumn(name = "OWNED_USER_ID")
private List<User> userList;
That's my class User. And i want to get list of all owned users by user.
here is my code:
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(User.class);
detachedCriteria.setProjection(Property.forName("userList.id"));
Session session = entityManager.unwrap(Session.class);
Criteria criteria = session.createCriteria(OfferStorage.class);
criteria.add(Subqueries.propertyIn("user.id", detachedCriteria));
criteria.list();
And it's return me following error
could not resolve property: userList.id
It's same if u use userList.user.id. Any ideas?

Well that was fast.
If some else would have problem with it there is answer
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(User.class);
detachedCriteria.createAlias("userList", "userList");
detachedCriteria.add(Restrictions.eq("id", userId ));
detachedCriteria.setProjection(Property.forName("userList.id"));
Session session = entityManager.unwrap(Session.class);
Criteria criteria = session.createCriteria(OfferStorage.class);
criteria.add(Subqueries.propertyIn("user.id", detachedCriteria));
criteria.list();

Related

IdentifierGenerationException: attempted to assign id from null one-to-one property + #MapsId + OneToOne bidirectional

I'm getting error
org.hibernate.id.IdentifierGenerationException: attempted to assign id from null one-to-one property.
The code snippets:
User.java
#Entity
#Table(schema = "public", name = "user_01")
public class User {
#Id
#GeneratedValue(generator = "UUID")
#GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
#Column(name = "id", updatable = false, nullable = false)
private UUID id;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
#JoinColumn(name = "user")
private UserInformation userInformation;
UserInformation .java
#Entity
#Table(schema = "public", name = "user_information_06")
public class UserInformation {
#Id
#Column(name = "id")
private UUID id;
#MapsId
#OneToOne(mappedBy = "userInformation")
private User user;
UserInformationService.java
// CREATE
public UserInformationBean createUserInformation(UserInformationBean userInformationBean) {
if(userInformationBean == null || userInformationBean.getUserId() == null)
return null;
User user = userRepository.findById(userInformationBean.getUserId()).orElse(null);
if(user == null)
return null;
UserInformation userInformation = user.getUserInformation();
if(userInformation != null) {
System.err.println("User Information exists !! " + userInformation.getId());
return null;
}
userInformation = new UserInformation();
userInformation.setFirstname(userInformationBean.getFirstname());
userInformation.setLastname(userInformationBean.getLastname());
userInformation.setGender(userInformationBean.getGender());
userInformation.setDateOfBirth(userInformationBean.getDateOfBirth());
userInformation.setProfession(userInformationBean.getProfession());
userInformation.setUpdatedOn(Timestamp.valueOf(LocalDateTime.now()));
user.setUserInformation(userInformation);
userInformation.setUser(user);
user = userRepository.save(user);
return userInformation.toBean();
}
After changing the below:
user = userRepository.save(user);
To:
userInformation = userInformationRepository.save(userInformation);
It works fine! Still want to know the reason and why it can't be persisted via User entity.

Hibernate criteria cannot fetch rows could not resolve property

Hi i have these 2 basic entity mapping for postgresql db, and i have wrote criteria for
fetching all activated user which have same key it is showing this error
org.hibernate.QueryException: could not resolve property: key.id of: com.sar.dfsapp.modal.ActivatedUser
#Entity
#Table(name = "activated_user")
public class ActivatedUser implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false, length = 11)
private long id;
#ManyToOne
#JoinColumn(name = "key_id", nullable = false)
private Key key;
}
#Entity
#Table(name = "key")
public class Key implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", nullable = false, length = 11)
private long id;
#Column(name = "key_code", nullable = false)
private String keyCode;
}
Below is my criteria i have tried.
Criteria c = getSession().createCriteria(ActivatedUser.class);
c.add(Restrictions.eq("key.id", id));
List<ActivatedUser> result = c.list();
try this :
Criteria c = getSession().createCriteria(ActivatedUser.class);
Criteria keyCriteria = criteria.createCriteria("key", CriteriaSpecification.INNER_JOIN);
keyCriteria.add(Restrictions.eq("id", id));
List<ActivatedUser> result = c.list();
it there the same error ?

Do I need to Set Foreign key value in JPA?

I have two table:
CREATE TABLE [LeTYPE](
[LeNAME] [varchar](100) NOT NULL,
[Le_DESC] [varchar](500) NULL,
[LeFOR] [varchar](50) NOT NULL,
CONSTRAINT [PK_LeTYPE] PRIMARY KEY CLUSTERED
(
[LeNAME] ASC
)
)
CREATE TABLE [Le](
[SN] [int] IDENTITY(1,1) NOT NULL,
[LeNAME_FK] [varchar](100) NOT NULL,
[Le_SN] [int] NULL,
[LOWERRANGE] [float] NOT NULL,
[UPPERRANGE] [float] NOT NULL,
[Le_DESC] [varchar](500) NULL,
[COLOR] [varchar](45) NULL,
CONSTRAINT [Le_pk] PRIMARY KEY CLUSTERED
(
[SN] ASC
))
GO
ALTER TABLE [Le] WITH CHECK ADD CONSTRAINT [FK_Le_LeTYPE] FOREIGN KEY([LeNAME_FK])
REFERENCES [LeTYPE] ([LeNAME])
ON UPDATE CASCADE
ON DELETE CASCADE
GO
ALTER TABLE [Le] CHECK CONSTRAINT [FK_Le_LeTYPE]
GO
One tuple in LETYPE will have many LE.
JPA Entity generated by netbeans:
public class Letype implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 100)
#Column(nullable = false, length = 100)
private String Lename;
#Size(max = 500)
#Column(name = "Le_DESC", length = 500)
private String LeDesc;
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 50)
#Column(nullable = false, length = 50)
private String Lefor;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "LenameFk", fetch = FetchType.LAZY)
private List<Le> LeList;
}
public class Le implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#NotNull
#Column(nullable = false)
private Integer sn;
#Column(name = "Le_SN")
private Integer LeSn;
#Basic(optional = false)
#NotNull
#Column(nullable = false)
private double lowerrange;
#Basic(optional = false)
#NotNull
#Column(nullable = false)
private double upperrange;
#Size(max = 500)
#Column(name = "Le_DESC", length = 500)
private String LeDesc;
#Size(max = 45)
#Column(length = 45)
private String color;
#JoinColumn(name = "LeNAME_FK", referencedColumnName = "LeNAME", nullable = false)
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private Letype LenameFk;
}
Now, What I wanted was if I add a LETYPE from JSF view I would like to add multiple LE also at the same time.
LETYPE
-LE1
-LE2
-LE3
Do I need to set LenameFk manually in Le entity since I am getting
*Cannot insert the value NULL into column 'LENAME_FK'*? Why won't it automatically take it from Le enityt?
Note this snippet of code:
public class Le implements Serializable {
...
#ManyToOne(optional = false, fetch = FetchType.LAZY)
private Letype LenameFk;
...
}
optional = false means any instance of this entity must participate the relation, so, the foreign key field can not be null.
Your right, You need to set LenameFk manually in Le entity.
In General , for Bi-directional one-to-many two way relation , Accessor method should like below and assume entities are Customer and Order and one-to-many relation b/w them.
Customer.java
public Collection<Order> getOrders() {
return Collections.unmodifiableCollection(orders);
}
public void addToOrders(Order value) {
if (!orders.contains(value)) {
orders.add(value);
value.setCustomer(this);
}
}
public void removeFromOrders(Order value) {
if (orders.remove(value)) {
value.setCustomer(null);
}
}
Order.java
public void setCustomer(Customer value) {
if (this.customer != value) {
if (this.customer != null) {
this.customer.removeFromOrders(this);
}
this.customer = value;
if (value != null) {
value.addToOrders(this);
}
}
}
public Customer getCustomer() {
return customer;
}

Marshalling Error: failed to lazily initialize a collection of role (...), no session or session was closed

I`m using Eclipse RCP with EJB exposed like WebServices. My services beans looks like follows
#Override
#SuppressWarnings("unchecked")
public List<Author> listAll() {
final Query query = this.entityManager.createQuery("from Author");
final List<Author> authors = query.getResultList();
return authors;
}
The two entityes are:
#Entity
#Table(name = "books")
public class Book implements Serializable {
#Id
private int id;
private String title;
private String summary;
private String isbn;
#Column(name = "published")
private Date publishingDate;
#Column(name = "created")
private Date createdAt;
#Column(name = "updated")
private Date modifiedAt;
#ManyToMany
#JoinTable(
name = "book_authors",
joinColumns = #JoinColumn(name = "book_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "author_id", referencedColumnName = "id"))
private List<Author> authors;
and
#Entity
#Table(name = "authors")
public class Author implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private int id;
#Column(name = "first_name")
private String firstName;
#Column(name = "middle_name")
private String middleName;
#Column(name = "last_name")
private String lastName;
#Column(name = "created")
private Date createdAt;
#Column(name = "updated")
private Date modifiedAt;
#ManyToMany
#JoinTable(
name = "book_authors",
joinColumns = #JoinColumn(name = "author_id", referencedColumnName = "id"),
inverseJoinColumns = #JoinColumn(name = "book_id", referencedColumnName = "id"))
private List<Book> books;
In my TestWSCLient i`m trying to do something like this
AuthorServiceBeanServiceLocator locator = new AuthorServiceBeanServiceLocator();
AuthorServiceBean service = locator.getAuthorServiceBeanPort();
Author[] authors = service.listAll();
for(Author a : authors){
System.out.println(a.getFirstName());
}
and I`m getting this error
{....//xml.apache.org/axis/}stackTrace:Marshalling Error: failed to lazily initialize a collection of role: ro.cgs.entities.Author.books, no session or session was closed
I`m mention that if I do not make the Many-To-Many relationship all works fine. Can anybody tell me what should I do to fix this problem ?
I use Hibernate for persistence.
Thanks.

JPA: persist does not insert into join table

All,
I am using JPA for this application and annotations for Mapping entities. I have an entity called UserStory and another one called Revision. There is a OneToMany for UserStory to Revision.
#Entity
#Table(name = "user_story")
#NamedNativeQueries({
#NamedNativeQuery(name = "storyBacklog", query = "SELECT userstory.rank AS rank, userstory.description AS description, userstory.estimate AS estimate, userstory.name AS name, "
+ "userstory.id AS id, userstory.status AS status FROM user_story userstory ORDER BY userstory.rank ASC", resultClass = UserStory.class),
#NamedNativeQuery(name = "getCos", query = "SELECT conditions.cos As cos FROM story_cos conditions WHERE conditions.story_id=?1", resultSetMapping = "cosMapping") })
#SqlResultSetMappings({ #SqlResultSetMapping(name = "cosMapping", columns = #ColumnResult(name = "cos")) })
public class UserStory implements Serializable {
private static final long serialVersionUID = 248298400283358441L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
...
#OneToMany(cascade = CascadeType.ALL)
#JoinTable(name = "story_revisions", joinColumns = #JoinColumn(name = "story_id"), inverseJoinColumns = #JoinColumn(name = "revision_id"))
private Set<Revision> revisions;
here's Revision entity:
#Entity
#Table(name = "revision")
public class Revision implements Serializable {
private static final long serialVersionUID = -1823230375873326645L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(nullable = false)
private String description;
#Column(name = "date_created", nullable = false)
#Temporal(TemporalType.TIMESTAMP)
private Date creationDate;
When I create a userStory; I add a revision on to it,
but the join table is not populated unless, I persist story first,
then add revision and merge it.
here's the code for saving a UserStory:
public UserStory saveUserStory(UserStory userStory) {
Revision revision = new Revision();
revision.setCreationDate(new Timestamp(System.currentTimeMillis()));
revision.setDescription("User story created");
Set<Revision> revisions = new HashSet<Revision>();
revisions.add(revision);
userStory.setRevisions(revisions);
return storyDao.create(userStory);
}
in StoryDao I call the persist method:
#Transactional(readOnly = false)
public UserStory create(UserStory userStory) {
if (userStory.getRank() == null) {
Integer highestRank = 0;
highestRank = (Integer) entityManager.createNativeQuery("select max(rank) from user_story")
.getSingleResult();
if (highestRank != null)
highestRank += 1;
else
highestRank = new Integer(1);
userStory.setRank(highestRank);
}
entityManager.persist(userStory);
LOGGER.debug("Added User Story with id " + userStory.getId());
entityManager.detach(userStory);
return userStory;
}
here's the SQL from LOGS
Hibernate:
insert
into
user_story
(description, estimate, name, rank, status)
values
(?, ?, ?, ?, ?)
Hibernate:
insert
into
revision
(date_created, description)
values
(?, ?)
Hibernate:
select
revision0_.id as id5_0_,
revision0_.date_created as date2_5_0_,
revision0_.description as descript3_5_0_
from
revision revision0_
where
revision0_.id=?
Hibernate:
select
userstory0_.id as id3_1_,
userstory0_.description as descript2_3_1_,
userstory0_.estimate as estimate3_1_,
userstory0_.name as name3_1_,
userstory0_.rank as rank3_1_,
userstory0_.status as status3_1_,
revisions1_.story_id as story1_3_3_,
revision2_.id as revision2_3_,
revision2_.id as id5_0_,
revision2_.date_created as date2_5_0_,
revision2_.description as descript3_5_0_
from
user_story userstory0_
left outer join
story_revisions revisions1_
on userstory0_.id=revisions1_.story_id
left outer join
revision revision2_
on revisions1_.revision_id=revision2_.id
where
userstory0_.id=?
I can see from here it saves the user story and revision, but then tries to run a join to see if the relation exists before doing an insert into the join table. Which of course it will not find because I am creating this object.
How do it get the join table populated in this case?
Works now. Here's the updated code
revisions.add(revision);
userStory = storyDao.create(userStory);
userStory.setRevisions(revisions);
return storyDao.update(userStory);
I am still not sure why this is required; the two step method where I persist an object then update it.