Basic Hibernate issues using and SQL query - java

I have an java Object Person with 3 properties firstname, lastname and username.
I have an Oracle stored procedure returning a result set with the 3 columns.
All works fine for that.
Now I have another stored procedure that will only return firstname and lastname but not username.
I get the following error:
Could not read column value from result set username
Hibernate tries to fetch the username property from the resultset.
If I remove the property username, then it works.
My config:
<sql-query name="normalise" callable="true" >
<return alias="val" class="com.nbfg.sipc.model.Person">
<return-property name="firstname" column="FIRST_NAME"/>
<return-property name="lastname" column="LASTNAME_NAME"/>
</return>
{call SCHSIPC.PKG_SIPC_APP.PRC_SIPC_NORMALISE_RS(?, ?, ?, ?, ?) }
</sql-query>
My Pojo (no annotation)
#Entity
public class Person {
private String firstname;
private String lastname;
private String username;
...
The call:
private Value call(String app, String cat, String col, String valeure, String query) {
try {
Query q = getSessionFactory().openStatelessSession().getNamedQuery(query);
q.setString(0, app).setString(1, cat).setString(2, col).setString(3, valeure);
return (Person) q.list().get(0);
} catch (org.hibernate.QueryTimeoutException ex) {
throw new IllegalArgumentException(ex.getCause().getMessage());
}
}
It all works fine if I remove the property username from my Pojo. I can I reuse the same PoJo?
Thank you

Thank you for the code. I am not 100% certain on this, but I believe that with Hibernate SQL queries must return all fields of the object you want the query to instantiate.
An alternative solution you may want to try is to rely on HQL and instantiate the object as needed. For example, SELECT new Person(firstName, lastName) from Person p where p.username = ...
This actually allows you to use any type (with fields of matching types) in your queries.
This would solve your immediate problem, but I am not sure how to address the use of stored procedures in this scenario. Hope this helps.

Well I guest if we are saying that there is no way to tell Hibernate to read only certain Columns in a ResultSet return by a StoreProcedur and that I need to create a separate POJO for each Type of result set, then this the answer.
If this right?

Related

Is there a way to return collection instead of entity in #Repository's #Query

I have a query:
#Query(
value = "select name, age, now() from received.scheme ;",
nativeQuery = true
)
public {???} selectData()
I cannot create or return an entity for such a scheme as there is no natural id in it, so is there a way to return something like List<Triple<String, Int, LocalDateTime>>?
you can create another class with the required properties which you want to retrieve from the database and then you can return that class as List<Class>.
In your code you get the data from: scheme
So the Entity SchemeEntity should contains those three fields:
name
age
now (creationDate for example it depend on your logic)
Then your method should be like this:
#Query(value = "select name, age, now() from received.scheme ;",
nativeQuery = true
)
public List<SchemeEntity> selectData();
You can provide a PROJECTION entity which will have 3 attributes and must provide a parametrized constructor with those 3 attributes you want to fetch ,or you can still get them as a List<Object[]> and then hydrate your entity.
I've tried those things but what worked for me is using ctid as an #Id. Since I only needed some sort of a mock id, it worked fine.

Map result of a sql query to pojo using spring Data JPA

I am a student learning Spring data jpa. I am trying to solve some of practice coding questions. I have a question which i could not find answer to.
I have a database table by name MYDB which has fields:
(id, firstname, lastname, rollno, major, country)
And i have an sql query like this:
select Count(*) as counts, lastname as last_name, major as major_field from MYDB group by country
The above query returns three fields: counts(which is not a db column), last_name and major_field.
I have a POJO like this:
public class MyPojo {
private int counts;
private String lastName;
private String majorField;
// Getters and Setters of all data members here
...................
}
My question is how do i map the result that i got from sql query to my POJO? I need to assign:
counts = counts(from sql query), lastName = last_name(from sql query), majorField = major_field(from sql query).
I am stuck at this point and do not know how to implement further to map result of sql query to POJO:
public interface MyRepo extends JpaRepository<MyPojo, String> {
#Query(value=MY_SQL_QUERY, nativeQuery = true)
List<MyPojo> findAll();
}
Ultimately i need to convert MyPojo to a Json object, but i know how to do that part. I am only stuck without ideas about assigning result of sql query to pojo.
Problem solved using interface-based projections:
https://www.baeldung.com/jpa-queries-custom-result-with-aggregation-functions#solution_interface_jpa
Use the javax.persistence #Column annotation to specify which values from the query are used to populate the fields of the Java object:
public class MyPojo {
#Column(name = "counts")
private int counts;
#Column(name = "last_name")
private String lastName;
... and so on
}
Here is a great tutorial on the annotations:
https://www.javaworld.com/article/3373652/java-persistence-with-jpa-and-hibernate-part-1-entities-and-relationships.html
You have to use TypedQuery and give your class name for executing and mapping your query result into pojos

Whats the best way to forma list of objects from different tables using Hibernate and spring

I am trying to create a list of objects that contains different types of logs from my db. I would like to build the list such that the order is by most recently made (a date created field that's in each of the tables).
So is the only way to do it by getting each list (4 different kinds of logs) and then cycle through them and put them in the new list by comparing them and getting the most recent one each time? This seems like it could take a long time if the list are really long which they may or may not be.
IS there a better way to do it with Hibernate where I could put all the tables together and have it do the work for me? The tables don't share any keys or anything for a normal join?
Any suggestions would be helpful.
contactLog
has columns (Id, memberId, phonenumber, email, address, dateChanged)
salaryLog
has columns (Id, memberId, salary, dateChanged)
relationsLog
has columns (Id, memberId, relationId, dateChanged)
personalInfoLog
has columns (Id, memberId, height, weight, eyeColor, hairColor, dateChanged)
The purpose of these logs is to indicate anytime someone changes information and Im trying to provide the user with a audit page that will show all changes to these different objects.
I suggest using UNION, but if I'm not mistaken, HQL does not support UNION, so you'll have to use native query and result transformer. Here's a sample:
public class Log {
private Long id;
private Long memberId;
private String logType;
private Date dateChanged;
// getters & setters here
}
public class LogService {
#PersistenceContext
private EntityManager em;
public List<Log> getLogs(){
final Session sess = em.unwrap(Session.class);
final SQLQuery query = session.createSQLQuery(
"select id,memberId,'CONTACT' as logType, dateChanged from contactLog"+
"union select id,memberId,'SALARY' as logType,dateChanged from salaryLog"+
"union select id,memberId,'RELATIONS' as logType,dateChanged from relationsLog"+
"union select id,memberId,'PERSONAL INFO' as logType,dateChanged from personalInfoLog "+
"order by dateChanged desc";
);
query.setResultTransformer(Transformers.aliasToBean(Log.class));
return query.list();
}
}
Notice that only common columns are selected (because you must select the same number of columns from each table when using union).
If you want to view the full details of the log, just use the id to load the specific log and the log type to know from which table you would have to look for the full information.
or
You could modify the query to concat all the changed information into one column for all the tables (which means adding a new field in Log.class).
public class Log {
private Long id;
private Long memberId;
private String logType;
private Date dateChanged;
private String changedInfo;
// getters & setters here
}
"select id,memberId,'CONTACT' as logType, dateChanged, phonenumber||','||email||','||address as changedInfo from contactLog"+
"union select id,memberId,'SALARY' as logType,dateChanged,salary as changedInfo from salaryLog"+
"union select id,memberId,'RELATIONS' as logType,dateChanged,relationId as changedInfo from relationsLog"+
"union select id,memberId,'PERSONAL INFO' as logType,dateChanged, height||','|| weight||','|| eyeColor||','|| hairColor as changedInfo from personalInfoLog "+
"order by dateChanged desc
An another approch will be to create a view on your database, and use spring and hibernate as usual.

How to return IDs on insert in mybatis and oracle with annotation

I am trying the following in Java
#Insert("INSERT INTO USERS (ID,NAME,AGE) VALUES(USER_SEQ.NEXTVAL,#{name},#{age})")
#Options(useGeneratedKeys=true, keyProperty="ID", keyColumn="ID")
public int insertUsers(User userBean);
It should return the new genarated ID, but its returning "1" always even though its making insertion into table in a proper way.
Can any one have tryied this "Getting IDs in return or insertion in MyBatis(annotation) with oracle"
Read the MyBatis Documentation.
The keyProperty is the field that MyBatis will set the key into by
getGeneratedKeys, or by a selectKey child element of the insert
statement.
So, given a Pojo with a field "id" with get and set methods. After the insert statement with the Mapper class is ran, the id field on the pojo will be set with the generated key value.
Thanks all for your responses, but i have got the solution here it is.....
#Insert("INSERT INTO USERS (NAME,AGE) VALUES(#{name},#{age})")
#SelectKey(statement="select STANDARDS_ID_SEQ.CURRVAL from dual", resultType = int.class, before = false, keyProperty = ID)
#Options(useGeneratedKeys=true, keyProperty="ID", keyColumn="ID")
now it will return the new created ID

Best SQL Option for Performance

I currently need to execute a database query that involves data from three separate tables.
(bases,member,sell_transaction)
The bases table looks like the following
base_id(PK) name state
The member table looks like the following
id(PK) last_name username email first_name
The sell_transaction table has the following schema
transaction_id(PK) city
state
base_id
date id
agentId
NOTE- these tables contain more columns, but they are irrelevant, so I am going to save the time and not write them out.
I am working on a transaction inquiry that involves data from all of these tables. I need to return this data in a TransactionItem that I am populating from these three tables
The TransactionItem as a Pojo looks like the following
public TransactionItem(){
private String firstName;
private String lastName;
private String email;
private String baseName;
private String city;
private String state;
private Date date;
public String getFirstName(){
return firstName;
}
public String setFirstName(String firstName){
this.firstName = firstName;
}
...
...///The rest of the getters and setters
...
...
}
Currently I am doing three separate selects from each table, which is taking longer then I would like. I would image that there is a way I could use a join or nested select statements,etc.
The data and conditions and their corresponding tables are as follows
I need...
first_name, last_name,id from member
I need
name and state from bases where base_id from sell_transaction is equal to base_id from bases
Again there is more that I need, but it is redundant to name them off, The idea should still be clear, I need to query data that is dependent on each other. I am not sure performance wise what is the best performance option. The amount of data that is being traversed could end up being very large or very small(not sure if that matters).
select
b.name,b.state,
s.city,s.state,s.duty,s.branch,s.date,
m.first_name,m.last_name,m.email,m.phone,m.id,s.transaction_id
from
bases as b, sell_transaction as s, member as m
where
s.agentId is null and
s.username = m.username and
b.base_id = s.duty
select first_name, last_name, member.id member_id, bases.name, bases.state
from bases, sell_transaction, member
where sell_transaction.base_id = bases.base_id
and member.id = sell_transaction.agentId;
I am going out on a limb here and guessing that agentID is the connection to member from sell_transaction, but it's not clear or obvious, and possibly incorrect (unless you clarify your data model).

Categories

Resources