I am creating a java bean from a master detail table. Lets call the master table A and Detail table B. When I make this in to a java bean I have BeanA and BeanB. BeanA will have all the relavant rows in the A table and will also have a list collection of BeanB (detail table B) based on the primarykey. So BeanA will look like
class BeanA {
String property1;
String Property2;
List<BeanB> lstpropery; //This is the data of detail table based on the primary key
}
In this scenerio I am using Spring JDBC to query the table. So when I query the table A and loop through the resultset and set the BeanA properties, I will also set the lstproperty by doing the query to B table.
so the code will be
String qry = "select * from A';
result = this.queryTemplate.query(qry, obj, new RowMapper(){
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
BeanA bean1= new BeanA();
bean1.setProperty1(rs.getString(1));
bean1.setProperty2(rs.getString(2));
bean1.setLstpropery(callTableB(String primaryKey)); // I see a performance issue here
return bean1;
}
});
Is there a better way to do this?
Use a left join :
select a.*, b.* from A a left outer join B b on a.id = b.aId
(You should in fact explicitely list all the columns and assign aliases to each of them).
This query will retrieve a row per couple A-B, and will also retrieve all the As which have no B.
For each row, see if you already have an A with the returned A ID. If not, construct the A and put it in a map (indexed by A ID). Then construct a B instance with the columns from the B table (unless the returned B ID is null, which means that the A has no B), and add it to the list of Bs of the A you got from the map or just constructed.
Note that ORMs like JPA make this tedious work much easier: they populate an object tree from a single request for you.
If you have a chance to use Hibernate, then lazy-fetching concept might be useful here.
Related
I use new in JPQL query like the following way
select
ob.property1,
NEW package1.CustomObject(item, dimension, material, product)
from mainTable ob
LEFT JOIN ....
The application complains about the coma after ob.property1 saying it is an unexpected token. It seems that you cannot use multiple column with a new inside the select clause. Can you help me
According to this you have the following options:
Wrapping the values in a type-safe Java object that will be returned as the results of the query.
select new package1.CustomObject(item, dimension, material, product)
from MainTable ...
The projection class must be fully qualified in the entity query, and it must define a matching constructor. The class here need not be mapped. It can be a DTO class. If it does represent an entity, the resulting instances are returned in the NEW state (not managed!).
HQL supports additional "dynamic instantiation" features.
The query can specify to return a List rather than an Object[] for scalar results.
select new list(item, dimension, material, product)
from MainTable ...
The results from this query will be a List<List> as opposed to a List<Object[]>.
Wrapping the scalar results in a Map
select new map(
item as iName,
dimension as iDimension,
material as iMaterial,
product as iProduct)
from MainTable ...
The results from this query will be a List<Map<String, Object>> as opposed to a List<Object[]>. The keys of the map are defined by the aliases given to the select expressions. If the user doesn’t assign aliases, the key will be the index of each particular result set column (e.g. 0, 1, 2, etc).
I have a LinQ query which is intended to Update the table concerned.
The code is as follows:
LINQHelperDataContext PersonalDetails = new LINQHelperDataContext();
var PerDetails1 = (from details in PersonalDetails.W_Details_Ts
where details.UserId == userId
select details).First();
PerDetails1.Side = "Bridge";
PerDetails1.TotalBudget = 4000000;
PersonalDetails.SubmitChanges();
However, this change/update does not get reflected in the DB. Also,this does not throw any exception.Please suggest.
Make sure W_Details_Ts has one (or more) member properties marked as primary key. L2S can't generate update or delete statements if it does not know the underlying table's PK member(s).
Here is my Schema :
Table t1:
x1 y1
1 2
Table t2:
x2 y2
1 'x1'
2 'y2'
I need to use dynamic SQL to join these two tables and the join column of table t1 should be decided by the value of column y2.
I tried a very ugly and not-working SQL of cause of no use.
select * from t1 join t2 t on t2.x2 = t1.(select y2 from t2 where x2=t.x2);
I am very new to dynamic SQL so not sure how to achieve this.
P.S. : The values above are just for example. Actually, both the tables are dynamically created hence not necessary the column names will be same. Also, the column numbers may differ hence pivoting might not be that useful
You don't need dynamic SQL, such more logic in the on clause:
select *
from t1 join
t2 t
on t2.x2 = t1.x1 and t2.y2 = 'x1' or
t2.x2 = t1.y1 and t2.y2 = 'y1';
In my experience this is best handled at the program level (creating these dynamic queries).
You don't know the table names but it doesn't mean you can't create a store for the dynamic names (ie. another table, called "tables_meta" that contains a listing of all the dynamic tables).
Likewise, if you wanted a dynamic table to have dynamic fields as well, you could create a table to store the mapping between the dynamic table created and the associated dynamic fields ("fields_meta" containing a one to many association between table and its dynamic fields).
Querying the "meta" tables for table name and then building your query programmaticly using that retrieved name (and likewise fields) can allow you run any queries you want against the dynamic objects.
As for joining dynamic tables specifically, doing so assumes you have some insight into the fields that result in a meaningful join. If this is the case, you could create your dynamic tables, but with at least one static field with meaningful data, that would allow you to query your "tables_meta" for a table, then build a query in your program with that result to join your table X on its static field "join_here" with (repeat read from tables meta to get Y) and join it on Y."join_here" (the static field)
Very rough example sudo code:
List<String> sql-getDynamicTables = "select table_name from tables_meta";<br />
(results in X, Y, Z...)
if(sql-getDynamicTables.size > 1) { (make sure we have stuff to join on)
(Start building the query for the join)
String sql-performJoin = "select * from" + sql-getDynamicTables.get(0);
for( each additional database found ) {
sql-performJoin += " join " + sql-getDynamicTables.get(index-i) + " on " + sql-getDynamicTables.get(index-i)+".staticField = "(or replace that with a separate variable containing the dynamic field)+ sql-getDynamicTables.get(0)".staticField, ";
}
(remove any trailing commas)
(add any where clause or whatever modifications to the query)
(run the query sql-performJoin)
}
Again, column names might not be the same but you can query for them like we do the dynamic table names and build the query with that instead of ".staticField" or whatever you choose.
Just make sure you know that the data your joining on provides a meaningful join.
Just as a note: Dynamic SQL is quite painful and introduces a lot of considerations (duplicating table names, etc). It might be worth investigating alternatives if your still up in the air about it.
This is my first time using the Entity Framework and I'm getting some confusing results. I know a particular table contains 3 distinct rows when I run this SQL query:
SELECT * FROM mytable WHERE service_month = 201012
When I run this query against the framework however, I get 3 rows, but they are all copies of the first row (VB syntax).
Dim temp = _context.mytable.Where(Function(x) x.service_month = 201012)
Did I set up something incorrectly? This is how I'd do it with LINQ to SQL so I feel like I'm missing something.
Fix your primary key definition in your EDMX. (If your table has no PK, add one.) When all rows return the same "key", the EF returns the same object instance.
I experienced this in Code First 5.0.13 when I had used a [Key] attribute in the business object that came from the wrong library. It should be
System.ComponentModel.DataAnnotations.KeyAttribute
I am currently writing a VBA-based Excel add-in that's heavily based on a Jet database backend (I use the Office 2003 suite -- the problem would be the same with a more recent version of Office anyway).
During the initialization of my app, I create stored procedures that are defined in a text file. Those procedures are called by my app when needed.
Let me take a simple example to describe my issue: suppose that my app allows end-users to select the identifiers of orders for which they'd like details. Here's the table definition:
Table tblOrders: OrderID LONG, OrderDate DATE, (other fields)
The end-user may select one or more OrderIDs, displayed in a form - s/he just has to tick the checkbox of the relevant OrderIDs for which s/he'd like details (OrderDate, etc).
Because I don't know in advance how many OrderID s/he will select, I could dynamically create the SQL query in the VBA code by cascading WHERE clauses based on the choices made on the form:
SELECT * FROM tblOrders WHERE OrderID = 1 OR OrderID = 2 OR OrderID = 3
or, much simpler, by using the IN keyword:
SELECT * FROM tblOrders WHERE OrderID IN (1,2,3)
Now if I turn this simple query into a stored procedure so that I can dynamically pass list of OrderIDs I want to be displayed, how should I do? I already tried things like:
CREATE PROCEDURE spTest (#OrderList varchar) AS
SELECT * FROM tblOrders WHERE OrderID IN (#OrderList)
But this does not work (I was expecting that), because #OrderList is interpreted as a string (e.g. "1,2,3") and not as a list of long values. (I adapted from code found here: Passing a list/array to SQL Server stored procedure)
I'd like to avoid dealing with this issue via pure VBA code (i.e. dynamically assigning list of values to a query that is hardcoded in my application) as much as possible. I'd understand if ever this is not possible.
Any clue?
You can create the query-statement string dynamically. In SQL Server you can have a function whose return value is a TABLE, and invoke that function inline as if it were a table. Or in JET you could also create a kludge -- a temporary table (or persistent table that serves the function of a temporary table) that contains the values in your in-list, one per row, and join on that table. The query would thus be a two-step process: 1) populate temp table with INLIST values, then 2) execute the query joining on the temp table.
MYTEMPTABLE
autoincrementing id
QueryID [some value to identify the current query, perhaps a GUID]
myvalue one of the values in your in-list, string
select * from foo
inner join MYTEMPTABLE on foo.column = MYTEMPTABLE.myvalue and MYTEMPTABLE.QueryId = ?
[cannot recall if JET allows ANDs in INNER JOIN as SQL Server does --
if not, adjust syntax accordingly]
instead of
select * from foo where foo.column IN (... )
In this way you could have the same table handle multiple queries concurrently, because each query would have a unique identifier. You could delete the in-list rows after you're finished with them:
DELETE FROM MYTEMPTABLE where QueryID = ?
P.S. There would be several ways of handling data type issues for the join. You could cast the string value in MYTEMPTABLE as required, or you could have multiple columns in MYTEMPTABLE of varying datatypes, inserting into and joining on the correct column:
MYTEMPTABLE
id
queryid
mytextvalue
myintvalue
mymoneyvalue
etc