How do I update multiple tables inside a named query? - java

I am using Eclipselink v2.3.3
I am getting this error
Error compiling the query [Credential.updateExistingCredentialNoPW: UPDATE Credential c SET c.active = :active, c.employee.address.streetAddress = :stadd, c.employee.address.city = :city, c.employee.address.province = :prov, c.employee.address.zip = :zip WHERE c.id = :id], line 1, column 46: invalid navigation expression [c.employee], cannot navigate association field [employee] in the SET clause target.
when I try to run my code.
Here are the affected named queries that prevents running my code
#NamedQuery(name = "Credential.updateExistingCredentialNoPW",
query = "UPDATE Credential c "
+ "SET c.active = :active, "
+ "c.employee.address.streetAddress = :stadd, "
+ "c.employee.address.city = :city, "
+ "c.employee.address.province = :prov, "
+ "c.employee.address.zip = :zip "
+ "WHERE c.id = :id"),
#NamedQuery(name = "Credential.updateExistingCredential",
query = "UPDATE Credential c "
+ "SET c.password = :pw, "
+ "c.active = :active, "
+ "c.employee.address.streetAddress = :stadd, "
+ "c.employee.address.city = :city, "
+ "c.employee.address.province = :prov, "
+ "c.employee.address.zip = :zip "
+ "WHERE c.id = :id"),
#NamedQuery(name = "Credential.updateSalary",
query = "UPDATE Credential c "
+ "SET c.employee.salary.value = :val WHERE c.id = :id")
Here is the class where I put all the named queries specified above
public class Credential implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(generator = "CRED_GEN", strategy = GenerationType.IDENTITY)
#Column(name = "CREDENTIAL_ID")
private long id;
// unique & not nullabe username
#Column(nullable = false, unique = true)
private String username;
#Column(nullable = false, name = "USER_KEY")
private String password;
#Column(nullable = false)
private boolean active;
#Column(nullable = false)
private int userLevel;
#OneToOne(cascade = CascadeType.PERSIST, fetch = FetchType.EAGER)
private Employee employee;
public Credential() {
}
public Credential(String username, String password, boolean active,
int userLevel, Employee employee) throws NoSuchAlgorithmException {
this.username = username;
this.setPassword(password);
this.active = active;
this.userLevel = userLevel;
this.employee = employee;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public int getUserLevel() {
return userLevel;
}
public void setUserLevel(int userLevel) {
this.userLevel = userLevel;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public String getPassword() {
return password;
}
public void setPassword(String password) throws NoSuchAlgorithmException {
this.password = Cryptography.getHash(password);
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
Am I doing it wrong?

It is not possible to update multiple tables with single sql query.
See https://forums.oracle.com/forums/thread.jspa?threadID=2223393.
So it's also not possible with Eclipselink.
You'll have to split this it two queries, or better use setters.

You can't. Either use a SQL query, or use Java code:
Credential c = em.find(Credential.class, credentialId);
c.setActive(active);
c.getEmployee().getAddress().setStreet(street);
...

Related

Hibernate Query Syntax exception hql error with entity java

I have a query where i am joining two entities java (tables ) Command and User. I create sql hql query with left join and i get an org.hibernate.hql.ast.QuerySyntaxException: unexpected token error
I think that i have a problem with my left join syntax and also my second select.
My entities
#Entity
#Table(name = "Users")
public class User {
private int idUser;
private String login;
private String password;
private List<Command> commands = new ArrayList<>();
public User() { }
public User( String login, String password ) {
super();
this.setLogin( login );
this.setPassword( password );
}
#Id
#Column(name = "USER_ID", unique = true, nullable = false, scale = 0)
public int getIdUser() {
return idUser;
}
#Column(name = "USER_LOGIN", nullable = false)
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
#Column(name = "USER_PASSWORD", nullable = false)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "utilisateur")
public List<Command> getCommands() {
return commands;
}
public String toString() {
return this.idUser + ": " + this.login + "/" + this.password
;
}
}
#Entity
#Table(name="Commands")
public class Command {
private int idCommand;
private User utilisateur;
private Date commandDate;
public Command() {}
public Command( User user, Date commandDate ) {
this.setUser( user );
this.setCommandDate( commandDate );
}
#Id
#Column(name = "CMD_Id", unique = true, nullable = false, scale = 0)
public int getIdCommand() {
return idCommand;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "USER_ID")
public User getUtilisateur() {
return user;
}
public void setUtilisateur(User user) {
this.user = user;
}
#Column(name = "CMD_DATE")
#Temporal(TemporalType.TIMESTAMP)
public Date getCommandDate() {
return commandDate;
}
public void setCommandDate(Date commandDate) {
this.commandDate = commandDate;
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append( "Commande de >> " ).append( this.user )
.append( " - " ).append( this.commandDate ).append( "\n" );
return builder.toString();
}
}
And my hql query
select us.login,us.password
from User us left join Command cmd on us.idUser = cmd.utilisateur.idUser
AND us.idUser not in (SELECT utilisateur.idUser from Command )
ORDER BY us.idUser desc
I don't know what is the problem with my hql query. I Use the entity java in my hql query. AnyOne can i tell me how can i write correctly my hql query with a good syntax hql.
If you need the users login and password of users without commands the following might help
select us.login,us.password
from User us
where us.idUser not in (select c.user.idUser from Command c)
order by us.idUser desc

Mapping hibernate SQLQuery native return an empty object in java entity

I have two tables in my oracle database
my table data base
And two entities user and command
#Entity
#Table(name = "Users")
public class User {
private int idUser;
private String login;
private String password;
private List<Command> commands = new ArrayList<>();
public User() { }
public User( String login, String password ) {
super();
this.setLogin( login );
this.setPassword( password );
}
#Id
#Column(name = "USER_ID", unique = true, nullable = false, scale = 0)
public int getIdUser() {
return idUser;
}
#Column(name = "USER_LOGIN", nullable = false)
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
#Column(name = "USER_PASSWORD", nullable = false)
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#OneToMany(fetch = FetchType.LAZY, mappedBy = "utilisateur")
public List<Command> getCommands() {
return commands;
}
public String toString() {
return this.idUser + ": " + this.login + "/" + this.password
;
}
}
#Entity
#Table(name="Commands")
public class Command {
private int idCommand;
private User utilisateur;
private Date commandDate;
public Command() {}
public Command( User user, Date commandDate ) {
this.setUser( user );
this.setCommandDate( commandDate );
}
#Id
#Column(name = "CMD_Id", unique = true, nullable = false, scale = 0)
public int getIdCommand() {
return idCommand;
}
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "USER_ID")
public User getUtilisateur() {
return user;
}
public void setUtilisateur(User user) {
this.user = user;
}
#Column(name = "CMD_DATE")
#Temporal(TemporalType.TIMESTAMP)
public Date getCommandDate() {
return commandDate;
}
public void setCommandDate(Date commandDate) {
this.commandDate = commandDate;
}
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append( "Commande de >> " ).append( this.user )
.append( " - " ).append( this.commandDate ).append( "\n" );
return builder.toString();
}
}
and my service java class
#Service
#Transactional
public class MyServiceImpl implements MyService {
private static final long serialVersionUID = 8393594103219622298L;
private static final String MY_ADVANCED_REQUEST
="select us.USER_ID, cd.CMD_DATE, us.USER_PASSWORD " +
"from Users us , Commands cd ON us.USER_ID = cd.USER_ID " +
"where us.USER_ID = cd.USER_ID " +
"AND us.USER_ID = 5";
public List<Object> findUsersCmd() {
String query1 = MY_ADVANCED_REQUEST;
SQLQuery queryObj = sessionFactory.getCurrentSession().createSQLQuery(query1);
List<Object> lstObj =queryObj.list();
return lstObj;
}
}
I get an empty list in this line List lstObj =queryObj.list(); .
I use a request SQLQuery native not jpa.
I want to get 1 object for us.USER_ID = 5(even if I don't have an us.USER_ID = 5 in table commands), 3 objects for us.USER_ID=1 (because 3 rows in Commands table); 1 object for us.USER_ID=6 (because 1 rows in Commands table)
How can i solve my problem to return a valeur for my us.USER_ID = 5 ?
Left outer join returns all the rows from first table and only matched rows from second table.(though the user_id=5 is not present in commands table it can be retrieved)
private static final String MY_ADVANCED_REQUEST
="select us.USER_ID, cd.CMD_DATE, us.USER_PASSWORD " +
"from Users us LEFT JOIN Commands cd ON us.USER_ID = cd.USER_ID ";

'select count(*) from' is replaced by 'select count(where)' in spring jpa native query when using pagination

I am using a native query in JPA repository inside #Query annotation
#Query(value = " select * from message where id in(select if(coalesce(a.maxId,0)>coalesce(b.maxId,0), a.maxId, b.maxId) maxId from (select from_number, to_number, " +
" max(id) maxId,direction,type from message where direction='INCOMING' group by from_number, to_number having sum(type= :type)) as a " +
" left join ( select from_number, to_number, max(id) maxId, direction, type from message where direction = 'OUTGOING' and schedule_id is null " +
" group by from_number, to_number) as b on a.from_number=b.to_number and a.to_number=b.from_number) order by generated_time desc ", nativeQuery = true)
Page<Message> getLatestMessageFromThread(#Param("type") String type, Pageable page);
The problem is when i execute this query i am getting syntax error. When i checked the logs it is showing that the query to take count of total messages in query is like below
select count(where) from message where id in(select if(coalesce(a.maxId,0)>coalesce(b.maxId,0),
a.maxId, b.maxId) maxId from (select from_number, to_number, max(id) maxId,direction,type from
message where direction='INCOMING' group by from_number, to_number having sum(type= 'REVIEW'))
as a left join ( select from_number, to_number, max(id) maxId, direction, type from message
where direction = 'OUTGOING' and schedule_id is null group by from_number, to_number) as b
on a.from_number=b.to_number and a.to_number=b.from_number)
The count(*) is replaced by count(where)
The entity class for message table is here.
#Entity
#Table(name = "message")
public class Message implements Comparable<Message> {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "to_number")
private String toNumber;
#Column(name = "from_number")
private String fromNumber;
#Column(name = "message")
private String message;
#Enumerated(EnumType.STRING)
#Column(name = "direction")
private MessageDirection direction;
#Enumerated(EnumType.STRING)
#Column(name = "status")
private MessageStatus status;
#Enumerated(EnumType.STRING)
#Column(name = "type")
private KeywordType type;
#Column(name = "keyword_matched")
private String keywordMatched;
#Column(name = "generated_time")
private Timestamp generatedTime;
#Column(name = "scheduled_time")
private Timestamp scheduledTime;
#Column(name = "details")
private String details;
#Enumerated(EnumType.STRING)
#Column(name = "read_status")
private MessageReadStatus readStatus;
#Column(name = "delivery_code")
private String deliveryCode;
#Column(name = "delivery_description")
private String deliveryDescription;
#Column(name = "data", columnDefinition = "json")
private String messageData;
#ManyToOne
#JoinColumn(name = "schedule_id")
private Schedule schedule;
public Message() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getToNumber() {
return toNumber;
}
public void setToNumber(String toNumber) {
this.toNumber = toNumber;
}
public String getFromNumber() {
return fromNumber;
}
public void setFromNumber(String fromNumber) {
this.fromNumber = fromNumber;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public MessageDirection getDirection() {
return direction;
}
public void setDirection(MessageDirection direction) {
this.direction = direction;
}
public MessageStatus getStatus() {
return status;
}
public void setStatus(MessageStatus status) {
this.status = status;
}
public KeywordType getType() {
return type;
}
public void setType(KeywordType type) {
this.type = type;
}
public Timestamp getGeneratedTime() {
return generatedTime;
}
public void setGeneratedTime(Timestamp generatedTime) {
this.generatedTime = generatedTime;
}
public Timestamp getScheduledTime() {
return scheduledTime;
}
public void setScheduledTime(Timestamp scheduledTime) {
this.scheduledTime = scheduledTime;
}
public Schedule getSchedule() {
return schedule;
}
public void setSchedule(Schedule schedule) {
this.schedule = schedule;
}
public String getKeywordMatched() {
return keywordMatched;
}
public void setKeywordMatched(String keywordMatched) {
this.keywordMatched = keywordMatched;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
public MessageReadStatus getReadStatus() {
return readStatus;
}
public void setReadStatus(MessageReadStatus readStatus) {
this.readStatus = readStatus;
}
public String getDeliveryCode() {
return deliveryCode;
}
public void setDeliveryCode(String deliveryCode) {
this.deliveryCode = deliveryCode;
}
public String getMessageData() {
return messageData;
}
public void setMessageData(String messageData) {
this.messageData = messageData;
}
public String getDeliveryDescription() {
return deliveryDescription;
}
public void setDeliveryDescription(String deliveryDescription) {
this.deliveryDescription = deliveryDescription;
}
}
Why it is getting replaced. How can i write the query in correct way ?
The solution is to use countQuery annotation parameter :
public interface Repository extends JpaRepository<Entity, Long> {
String QUERY = "FROM entity " +
" WHERE name ILIKE :name ";
#Query(
value = "SELECT * " + QUERY,
countQuery = "SELECT count(*) " + QUERY,
nativeQuery = true
)
Page<KDeploymentView> findBy(
#Param("name") String name,
Pageable p
);

delete query with where clause in HQL

I am new to hql and trying to delete the complete row in case of a match based on email.
Following is what I have tried.
Still I get a Persistence Exception.
public void unsubscribeEmailList(EmailListDto dataList) {
EmailList e =new EmailList(dataList);
Query q =sessionFactory.getCurrentSession().createQuery("delete from EmailList where email=:e");
q.setParameter("e", dataList);
int i=q.executeUpdate();
System.out.println(i);
}
Class EmailList is
#Entity
#Table(name = "email_list")
public class EmailList implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String email;
public EmailList(EmailListDto dto)
{
this.email=dto.getEmail();
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id", unique = true, nullable = false)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "email", nullable = false)
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
Try use this:
q.setParameter("e", e.getEmail());
public void unsubscribeEmailList(EmailListDto dataList) {
EmailList e =new EmailList(dataList);
Query q =sessionFactory.getCurrentSession().createQuery("delete from EmailList where email = :e");
q.setParameter("e", e.egetEmail() );
int i=q.executeUpdate();
System.out.println(i);
}
...
#NamedQueries(
{
#NamedQuery(name = "FindAllJobsEngineersParticipateInInterval",
query = "SELECT je.id FROM Stage1JobEngineer AS je " +
"JOIN je.job AS s1j " +
"WHERE "
+ " :absenceStartDateTime <= :absenceEndDateTime "
+ " AND :absenceStartDateTime <= s1j.endTime AND :absenceEndDateTime >= s1j.startTime " +
" AND je.engineer.id IN (:engineerIds) ")
})
#Entity
#Table(name = "ho_stage1_job_has_engineers")
public class Stage1JobEngineer extends CreatedByUserEntity implements Serializable {
...
...
// dao service call :
Query query = getSession().getNamedQuery( "FindAllJobsEngineersParticipateInInterval" );
query.setParameter( "absenceStartDateTime", startDate )
.setParameter( "absenceEndDateTime", endDate )
.setParameterList( "engineerIds", Arrays.asList(1L, 2L, 33L) );
List<Long> queryResult = query.list();
List<Long> result = queryRes != null ? queryResult : new ArrayList<>();
...

How to make a query using columns of a JoinTable in Rest Webservice with netbeans

How I can to do this query:
#NamedQuery(name = "Scuser.findFriends", query = "SELECT s FROM Scuser s, friends f WHERE f.firstid = :iduser and s.iduser = f.secondid")
in this class:
#Entity
#Table(name = "scuser")
#XmlRootElement
#NamedQueries({
#NamedQuery(name = "Scuser.findAll", query = "SELECT s FROM Scuser s"),
#NamedQuery(name = "Scuser.findByIduser", query = "SELECT s FROM Scuser s WHERE s.iduser = :iduser"),
#NamedQuery(name = "Scuser.findByUpassword", query = "SELECT s FROM Scuser s WHERE s.upassword = :upassword"),
#NamedQuery(name = "Scuser.findByUname", query = "SELECT s FROM Scuser s WHERE s.uname = :uname"),
#NamedQuery(name = "Scuser.findByTpoints", query = "SELECT s FROM Scuser s WHERE s.tpoints = :tpoints"),
// #NamedQuery(name = "Scuser.findFriends", query = "SELECT s FROM Scuser s, friends f WHERE f.firstid = :iduser and s.iduser = f.secondid"),
#NamedQuery(name = "Scuser.findByUnameUpassword", query = "SELECT s FROM Scuser s WHERE s.uname = :uname and s.upassword = :upassword")})
public class Scuser implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 2147483647)
#Column(name = "iduser")
private String iduser;
#Size(max = 200)
#Column(name = "upassword")
private String upassword;
#Size(max = 200)
#Column(name = "uname")
private String uname;
// #Max(value=?) #Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
#Column(name = "tpoints")
private Double tpoints;
#JoinTable(name = "friends", joinColumns = {
#JoinColumn(name = "firstid", referencedColumnName = "iduser")}, inverseJoinColumns = {
#JoinColumn(name = "secondid", referencedColumnName = "iduser")})
#ManyToMany
private Collection<Scuser> scuserCollection;
#ManyToMany(mappedBy = "scuserCollection")
private Collection<Scuser> scuserCollection1;
#ManyToMany(mappedBy = "scuserCollection")
private Collection<Beach> beachCollection;
public Scuser() {
}
public Scuser(String iduser) {
this.iduser = iduser;
}
public String getIduser() {
return iduser;
}
public void setIduser(String iduser) {
this.iduser = iduser;
}
public String getUpassword() {
return upassword;
}
public void setUpassword(String upassword) {
this.upassword = upassword;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public Double getTpoints() {
return tpoints;
}
public void setTpoints(Double tpoints) {
this.tpoints = tpoints;
}
#XmlTransient
public Collection<Scuser> getScuserCollection() {
return scuserCollection;
}
public void setScuserCollection(Collection<Scuser> scuserCollection) {
this.scuserCollection = scuserCollection;
}
#XmlTransient
public Collection<Scuser> getScuserCollection1() {
return scuserCollection1;
}
public void setScuserCollection1(Collection<Scuser> scuserCollection1) {
this.scuserCollection1 = scuserCollection1;
}
#XmlTransient
public Collection<Beach> getBeachCollection() {
return beachCollection;
}
public void setBeachCollection(Collection<Beach> beachCollection) {
this.beachCollection = beachCollection;
}
#Override
public int hashCode() {
int hash = 0;
hash += (iduser != null ? iduser.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Scuser)) {
return false;
}
Scuser other = (Scuser) object;
if ((this.iduser == null && other.iduser != null) || (this.iduser != null && !this.iduser.equals(other.iduser))) {
return false;
}
return true;
}
#Override
public String toString() {
return "REST.Scuser[ iduser=" + iduser + " ]";
}
}
If I understand correctly, you have the ID of a user, and you want to get the friends of the user identified by this ID. The easiest way is to do
Scuser user = em.find(User.class, userId);
Collection<Scuser> friends = user.getScuserCollection();
If you want to do it using a JPQL query, you just need
select friend from Scuser user
inner join user.scuserCollection friend
where user.id = :userId
Note that your mapping isn't right: scuserCollection1 and beachCollection are both mapped by the same attribute. You should also choose better names for your associations (like friends for example, instead of scuserCollection).

Categories

Resources