Caused by: java.sql.SQLException: Column 'id' not found - java

I want to get some fields and then set it to my Test.entity. My SQL query:
query = "SELECT t.id as tId, t.test_name, t.duration, q.id as qId, " +
"q.question as question, q.is_multichoice as is_multichoice, " +
"q.is_open as is_open, a.id as aId, a.answer_text as answer_text FROM result r " +
"JOIN test t ON r.test_id = t.id " +
"JOIN user u ON r.user_id = u.id " +
"JOIN question q ON t.id = q.test_id JOIN answer a ON q.id = a.question_id " +
"WHERE t.id = :testId AND u.id = :userId AND r.permission = :permissionId " +
"AND q.archived = false AND a.archived = false", resultClass = com.bionic.entities.Test.class)
Test Entity:
public class Test {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "duration", nullable = false)
private int duration;
#Column(name = "test_name", nullable = false, unique = true)
private String testName;
#Column(name = "archived", nullable = false)
private boolean archived;
#OneToMany(mappedBy = "test", fetch = FetchType.EAGER)
private Set<Question> questions;
#ManyToMany(mappedBy = "tests")
private Set<User> users;
Question Entity:
public class Question {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "is_multichoice", nullable = false)
private boolean isMultichoice;
#Column(name = "is_open", nullable = false)
private boolean isOpen;
#Column(name = "picture")
private String picture;
#Column(name = "question")
private String question;
#ManyToOne
#JoinColumn(name = "test_id", nullable = false)
private Test test;
#Column(name = "archived", nullable = false)
private boolean isArchived;
#OneToMany(mappedBy = "question", fetch = FetchType.EAGER)
private Set<Answer> answers;
Answer Entity:
public class Answer {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "answer_text", nullable = false)
private String answerText;
#Column(name = "mark", nullable = false)
private int mark;
#ManyToOne
#JoinColumn(name = "question_id")
private Question question;
#Column(name = "picture")
private String picture;
#Column(name = "archived", nullable = false)
private boolean isArchived;
However, after executing this query i am getting exeption :
Caused by: java.sql.SQLException: Column 'id' not found.
DAO.class:
public Test getCurrentTest(long id, long testId, long permissionId) {
Query query = em.createNamedQuery("getCurrentTestById");
query.setParameter("userId", id);
query.setParameter("testId", testId);
query.setParameter("permissionId", permissionId);
return (Test) query.getSingleResult();
}
What am i doing wrong?

Your query doesn't return a field named id. It has fields named aId, qId, and tId.
You need to use the correct column names in your entities. For example, in your Test entity, you declared a column named id. Except your query doesn't return a column named id, it returns a column named tId. See below for an example of what needs to be changed.
public class Test {
#tId
#Column(name = "tId")
#GeneratedValue(strategy = GenerationType.AUTO)
private long tId;
....

Related

Populate DTO using query with JOIN

I have this main Product table:
#Table(name = "product")
public class Product implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, updatable = false, nullable = false)
private int id;
#Column(name = "user_id", length = 20)
private Integer userId;
#Column(name = "title", length = 75)
private String title;
#Column(name = "meta_title", length = 100)
private String metaTitle;
#Column(name = "status", length = 100)
private String status;
}
Additional table for storing categories that should be returned as List:
#Table(name = "product_category")
public class ProductCategory implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, updatable = false, nullable = false)
private int id;
#Column(name = "product_id", length = 4)
private Integer productId;
#Column(name = "category_id", length = 20)
private Integer categoryId;
}
Additional table for storing Payment Methods that should be returned as List:
#Table(name = "product_payment_methods")
public class ProductPaymentMethods implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, updatable = false, nullable = false)
private int id;
#Column(name = "product_id", length = 20)
private Integer productId;
#Column(name = "payment_methods", length = 20000)
private String paymentMethods;
}
I want to return a result like this:
id | title | categoryId | paymentMethods |
1 | test | 34, 43 | 345, 7, 5 |
5 | test2 | 64,5, 3 | 654, 3, 5 |
I tried this:
SELECT *
FROM Product
INNER JOIN product_category ON Product.id = product_category.productId
INNER JOIN product_payment_methods ON Product.id = product_payment_methods.productId
WHERE userId = 1
What is the proper way to populate this DTO?
public class ProductFullDTO {
private int id;
private Integer userId;
private List<Integer> categories;
private List<String> paymentMethods;
}
If, as indicated in your comments, you need query your information with HQL a good way to proceed can be the following.
First, modify your Product entity an include relationships for both ProductCategory and ProductPaymentMethods, something like:
#Table(name = "product")
public class Product implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, updatable = false, nullable = false)
private int id;
#Column(name = "user_id", length = 20)
private Integer userId;
#Column(name = "title", length = 75)
private String title;
#Column(name = "meta_title", length = 100)
private String metaTitle;
#Column(name = "status", length = 100)
private String status;
#OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ProductCategory> categories;
#OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
private List< ProductPaymentMethods> paymentMethods;
// Setters and getters, omitted for brevity
}
Modify both ProductCategory and ProductPaymentMethods to accommodate the entities relationship:
#Table(name = "product_category")
public class ProductCategory implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, updatable = false, nullable = false)
private int id;
// Please, feel free to change the insertable and updatable attributes to
// fit your needs
#Column(name = "product_id", length = 4, insertable=false, updatable=false)
private Integer productId;
#ManyToOne(fetch= FetchType.LAZY)
#JoinColumn(name="product_id")
private Product product;
#Column(name = "category_id", length = 20)
private Integer categoryId;
// Setters and getters, omitted for brevity
}
#Table(name = "product_payment_methods")
public class ProductPaymentMethods implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id", unique = true, updatable = false, nullable = false)
private int id;
// Please, feel free to change the insertable and updatable attributes to
// fit your needs. By the way, why here the length is 20 and not 4?
#Column(name = "product_id", length = 20, insertable=false, updatable=false)
private Integer productId;
#ManyToOne(fetch= FetchType.LAZY)
#JoinColumn(name="product_id")
private Product product;
#Column(name = "payment_methods", length = 20000)
private String paymentMethods;
}
With this setup, as you can see in the Hibernate documentation - it is for an old Hibernate version, but it is correct today, you can use fetch joins to obtain the required information:
A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection.
For your example, consider the following HQL (assume outer join semantics, modify it as appropriate):
select product
from Product as product
left join fetch product.categories
left join fetch product.paymentMethods
where product.userId = 1
This will provide you the list of products for userId 1, with all the associated references to categories and payment methods initialized.
The conversion between the entity and the DTO should be straightforward:
Session session = ...
List<Product> products = session.createQuery(
"select product " +
"from Product as product " +
" left join fetch product.categories " +
" left join fetch product.paymentMethods " +
"where product.userId = :userId", Product.class)
.setParameter( "userId", 1)
.getResultList();
List<ProductFullDTO> productFullDTOs = null;
if (products != null) {
productFullDTOs = products.stream()
.map((product -> {
ProductFullDTO productFullDTO = new ProductFullDTO();
productFullDTO.setId(product.getId());
productFullDTO.setUserId(product.getUserId());
List<ProductCategory> categories = product.getCategories();
if (categories != null) {
List<Integer> categoriesIds = categories.stream()
.map(ProductCategory::getCategoryId)
.collect(Collectors.toList())
;
productFullDTO.setCategories(categoriesIds);
}
List<ProductPaymentMethods> paymentMethods = product.getPaymentMethods();
if (paymentMethods != null) {
List<String> paymentMethodsIds = paymentMethods.stream()
.map(ProductPaymentMethods::getPaymentMethods)
.collect(Collectors.toList())
;
productFullDTO.setPaymentMethods(paymentMethodsIds);
}
return productFullDTO;
}))
.collect(Collectors.toList())
;
}
System.out.println(productFullDTOs == null ? "No products found." : productFullDTOs.size() + " products found.");
You should use TypeHandler to finish this job. I just give paymentMethods as example.
#Results({
#Result(column = "product.id", property = "id"),
#Result(column = "user_id", property = "userId"),
#Result(column = "category_id", property = "categories"),
#Result(column = "payment_methods", property = "paymentMethods" ,typeHandler= StrListTypeHandler.class),
})
#Select("SELECT * FROM Product INNER JOIN product_category ON Product.id = product_category.productId "
+ " INNER JOIN product_payment_methods ON Product.id = product_payment_methods.productId "
+ " WHERE userId = 1")
List<ProductFullDTO> getProduct();
// the below is TypeHandler implementation
#Component
public class StrListTypeHandler implements TypeHandler<List<String>> {
#Override
public void setParameter(PreparedStatement preparedStatement, int i, List<String> strings, JdbcType jdbcType) throws SQLException {
StringBuffer sb = new StringBuffer();
for (String s : strings) {
sb.append(s).append(",");
}
preparedStatement.setString(i, sb.toString().substring(0, sb.toString().length() - 1));
}
#Override
public List<String> getResult(ResultSet resultSet, String s) throws SQLException {
String[] arr = resultSet.getString(s).split(",");
return Arrays.asList(arr);
}
#Override
public List<String> getResult(ResultSet resultSet, int i) throws SQLException {
String[] arr = resultSet.getString(i).split(",");
return Arrays.asList(arr);
}
#Override
public List<String> getResult(CallableStatement callableStatement, int i) throws SQLException {
String[] arr = callableStatement.getString(i).split(",");
return Arrays.asList(arr);
}
}

How to use In clause in JPQL query with subquery

I have a entity classes as below
ExportMO.java
#Entity
#Table(name = "DATAEXPORTTEMPLATE")
#NamedQueries({
#NamedQuery(name = "ExportTemplateMO.getTemplatesByUser", query = "SELECT DISTINCT template FROM ExportTemplateMO template " +
"join template.fields exportFields WHERE template.eId IN (SELECT S1.dcid FROM SchoolMO S1 join S1.fields S2 WHERE S2.dcid = :userDCID)")
})
public class ExportMO implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "DATATEMPLATEID", unique = true, nullable = false)
private Long templateId;
#Column(name = "EID", nullable = true)
private Long eId;
#OneToMany(fetch=FetchType.EAGER, mappedBy="templateMO", cascade={CascadeType.ALL}, orphanRemoval=true)
private Set<ExportFieldMO> fields;
}
SchoolMO.java
#Entity
#Table(name = "SCHOOLSTAFF")
public class SchoolMO implements Serializable {
#Id
#Column(name = "DCID", unique = true, nullable = false)
private Long dcid;
#Column(name = "ID", unique = true)
private Long id;
#Column(name = "USERS_DCID", unique = false, nullable = false)
#JoinColumn(name="USERS_DCID",referencedColumnName="USERS_DCID",nullable=false)
private Long users_dcid;
#OneToMany(fetch=FetchType.EAGER, mappedBy="users_dcid", cascade={CascadeType.ALL}, orphanRemoval=true)
private Set<SchoolStaffLeanMO> fields;
}
Can someone help me how to use this using the IN clause for subquery.
If i try to use the same '=' instead of 'IN' i am able to get the results.
Thanks in advance.

JPA Entity and HQL JOIN command

I'm trying to achieve something like sql command below by using HQL and JPA.
Instead of "SELECT user_id..." I need SELECT OBJECT(o).
SELECT user_id FROM posix_user o INNER JOIN postgre_user n ON n.id=o.user_id WHERE n.name='USERNAME2'
I have some problems with this part of the code in JPA DAO:
public List<PosixUserEntity> listPosixUsers(final String uid_number) {
final StringBuilder queryString = new StringBuilder("SELECT OBJECT(o) FROM ");
queryString.append(this.entityClass.getSimpleName());
queryString.append(" o JOIN com.services.dao.user.jpa.UserEntity n ON (n.id=o.user_id) WHERE n.name LIKE :uid_number");
final Query findByNameQuery = entityManager.createQuery(queryString.toString()).setParameter("uid_number", uid_number);
return findByNameQuery.getResultList();
}
JOIN ON is not allowet here and I did not know how to replace it.
Also how can I replace com.services.dao.user.jpa.UserEntity by something cleaner.
There is my Entites, they may need to be improved:
#Entity
#Table(name = "posix_user")
public class PosixUserEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
//#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private String user_id;
#Column(name = "uid_number")
private String uid_number;
#Column(name = "home_directory")
private String home_directory;
#Column(name = "login_shell")
private String login_shell;
#Column(name = "group_id")
private String group_id;
//getters,setters....
#Entity
#Table(name = "postgre_user")
#SQLDelete(sql = "update postgre_user set status = 'removed' where id = ?")
public class UserEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(name = "name", unique = true, nullable = false)
private String name;
#Column(name = "password")
private String password;
#Enumerated(EnumType.STRING)
#Column(name = "status")
private UserStatus status;
#Column(name = "firstname")
private String firstName;
#Column(name = "lastname")
private String lastName;
#Column(name = "email")
private String email;
#Column(name = "usertype")
private String userType;
#OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
private List<UserRoleTargetGroupEntity> userRoleTargetGroupEntity;
#Column(name = "last_login")
private String lastLogin;
#Column(name = "previous_login")
private String previousLogin;
#JsonIgnore
#Column(name = "change_password_flag")
private Boolean userPasswordResetFlag;
#OneToOne(cascade=CascadeType.ALL)
#PrimaryKeyJoinColumn
private PosixUserEntity posixUserEntity;
You may also need to know that FOREIGN KEY (user_id) REFERENCES postgre_user (id) - it should look like that
Can you know how can I modify my SELECT?
I've tested a simplified version of your classes
#Entity
#Table(name = "posix_user")
public class PosixUserEntity {
#Id
#Column(name = "user_id")
private Long user_id;
// getter + setter
}
#Entity
#Table(name = "postgre_user")
public class UserEntity {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
#OneToOne(cascade=CascadeType.ALL)
#PrimaryKeyJoinColumn
private PosixUser posixUserEntity;
// getter + setter
}
And this JPQL query works as expected
String jpql = "SELECT p "
+ "FROM UserEntity n JOIN n.posixUserEntity p "
+ "WHERE n.name LIKE :uid_number)";
JOIN is allowed because you have mapped the relationship in UserEntity.
and you don't need to specify the complete name of your entity class.
Check if it has been included when you define your persistence unit.
Hope this helps.

How do I write join query in HQL?

i m trying to run a HQL query which is giving me error saying:
org.hibernate.QueryException: could not resolve property:
UserType of: EntityPack.UserTypeMenu
[from EntityPack.UserTypeMenu as utm ,EntityPack.UserType as ut
where utm.UserType.userTypeId=ut.userTypeId and ut.userTypeDesc like ' %ad%' ]
this is the function where i write query :
public ObservableList PostTableusertypemenu(String search, int q) {
ObservableList data;
data = FXCollections.observableArrayList();
List ll=null;
ll = pop.UrviewTable("from UserTypeMenu as utm ,UserType as ut "+
"where utm.UserType.userTypeId=ut.userTypeId"+
" and ut.userTypeDesc like ' %"+ search +"%' ");
Iterator ite = ll.iterator();
while (ite.hasNext()) {
UserTypeMenu obj = (UserTypeMenu) ite.next();
data.add(obj);
}
return data;
}
my UserType entity class :
#Entity
#Table(name = "user_type")
public class UserType {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Basic(optional = false)
#Column(name = "User_Type_Id")
private Integer userTypeId;
#Basic(optional = false)
#Column(name = "User_Type")
private String userType;
#Basic(optional = false)
#Column(name = "User_Type_Desc")
private String userTypeDesc;
#Basic(optional = false)
#Column(name = "Status")
private String status;
#Basic(optional = false)
#Column(name = "Markers")
private String markers;
}
UserTypeMenu Entity class :
#Entity
#Table(name = "user_type_menu")
#NamedQueries({
#NamedQuery(name = "UserTypeMenu.findAll", query = "SELECT u FROM UserTypeMenu u")})
public class UserTypeMenu implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Basic(optional = false)
#Column(name = "User_Type_Menu_Id")
private Integer userTypeMenuId;
#Basic(optional = false)
#Column(name = "Status")
private String status;
#Basic(optional = false)
#Column(name = "Markers")
private String markers;
#ManyToOne(optional = false)
private UserType userType;
#ManyToOne(optional = false)
private UserMenuMaster userMenuMaster;
#ManyToOne(optional = false)
private UserMenuBar userMenuBar;
}
what i want is to get data from UsertypeMenu based on Usertype description.
please help me..
thank you. :)
You don't write joins in HQL like in SQL, you use . notation to navigate through object graph. Try this
"from UserTypeMenu as utm where utm.userType.userTypeDesc like ' %"+ search +"%' "
Actually, you can use joins but directly on associations. Here is the same query but using join syntax
"from UserTypeMenu as utm join utm.userType ut where ut.userTypeDesc like ' %"+ search +"%' "
The benefit of using joins here is that you can specify, for example, left join if the relation is not mandatory and you don't want to lose any results because of inner join which is implicitly used when you use ..

HQL Problem

Hi every one I have these classe
#Entity
#Table(name = "login", uniqueConstraints={#UniqueConstraint(columnNames={"username_fk"})})
public class Login implements Serializable {
#Id
#Column(name = "id")
#GeneratedValue
private int id;
#Column(name = "password", length = 64)
private String password;
#Column(name = "roles", length = 32)
private String roles;
#OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
#OnDelete(action=OnDeleteAction.CASCADE)
#Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
#JoinColumn(name = "username_fk", nullable=false)
private Branch branch;
//some getter and sette
and
#Entity
#Table(name = "branch", uniqueConstraints = {#UniqueConstraint(columnNames = {"bname", "branch_fk"})})
public class Branch implements Serializable {
#Id
#GeneratedValue
private int id;
#Column(name = "username", length = 64, nullable=false)
private String userName;
#Column(name = "bname", length = 64)
private String branchName;
#Column(name = "officername", length = 64)
private String officerName;
#Column(name = "studcount")
private int studCount;
#Column(name = "blevel", columnDefinition="int default 0")
private int level;
#Column(name = "officeremail", length = 64)
private String officerEmail;
#Column(name = "confirmed", columnDefinition = "tinyint default 0")
private int confirmed;
#OneToOne(mappedBy = "branch", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
#OnDelete(action=OnDeleteAction.CASCADE)
#Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
private Login login;
when i use this Query :
executeQuery("select l from Login as l inner join l.branch as b where l.branch.bname = ?", username)
or this:
executeQuery("select b.login from Branch b where b.username = ?", username)
I have get this error:
org.hibernate.QueryException: could not resolve property: bname of: Data.Entity.Branch
but when use this code:
executeQuery("select b.login from Branch b where b.id = ?", username)
it's return correct result
I means this type of HQL just work for Primary key? or my maping have problem?
is there any way that I can use other field(except Primary Key) form joinable table?
Hibernate expects you to use the property name instead of the database column name, i.e. branchName insted of bname and userName instead of username.
So if you change your queries to
executeQuery("select l from Login as l inner join l.branch as b " +
"where l.branch.branchName = ?",
username);
and
executeQuery("select b.login from Branch b where b.userName = ?", username);
, everything should work as expected.

Categories

Resources