jpa select from two tables without relation - jpql

I have two jpa entities. Say A and B. A and B doesn't have any relation. Both of them have a common column "id". This id of A and id of B are completely different in the sense they are not related to each other.
Consider A:
id col1 col2
1 g l
5 h p
Consider B:
id col3 col4 col5
2 p h i
7 j l k
Now I should get a list consisting of both A and B entities sorted by their id values like below. Also need a extra new column that signifies its type:
type A 1 g 1
type B 2 p h i
type A 5 h p
type B 7 j l k
So this list should be returned in a result set and I should be able to add each resultant entity into its own respective list of A and B entity type finally.Can any one please help me with a query accomplish this. How should we do this through jpql?

Im not sure if this is good design but what you can do it is have a marker class and use that to have id and then have A & B extending marker class and use marker class to combine them.
Code Snippet:
Marker Class :
public class MarkerClass {
private int id;
public int getId() {
return id
}
// you need to implement a hash code and equals here
// you can have other common fields here
}
Class A :
public class A extends MarkerClass {
private String col1;
private String col2;
....
// getters for them
}
Class B
public class B extends MarkerClass {
private String col1;
private String col2;
....
// getters for them
}
Now you can combine them like
List< MarkerClass > listOfAllAAndB = new ArrayList();
listOfAllAAndB.addAll(allA);
listOfAllAAndB.addAll(allB);
Collections.sort(listOfAllAAndB, myCustomComparator);
Hope this helps.

Related

Groovy: Class fields default conditional values

I have below sample classes in my application:
class A {
Integer a
String b
Integer c = (a < 5) ? a+5 : a+10
}
class B {
void method1() {
A a = new A(a:4, b:"test")
log.print("c: ", a.c)
}
}
When my code is calling method1, then it outputs c = 14. but ideally it should 9.
How we can solve this without explicitly setting value for c?
Thanks in advance!
Not 100% sure of the question, and the example won't print anything as it will fail to add 5 to null, but an alternative might be to use the #Lazy annotation to defer creation of the value until such time as it is requested, ie:
class A {
Integer a
String b
#Lazy Integer c = { (a < 5) ? a+5 : a+10 }()
}
After it has been requested, it will keep this value, no matter how you change a and b (unless you change c yourself). From the question, I have no idea if this is what you want or not
class A {
Integer a
String b
def getC(){ (a < 5) ? a+5 : a+10 }
}
class B {
def method1() {
A a = new A(a:4, b:"test")
println("c: " + a.c)
}
}
new B().method1()

Compare a converted TreeSet from a String with another TreeSet Java 7

Using Java 7 I am looking for a way to compare a string that I converted to a TreeSet with another defined TreeSet.
Here is an example:
public static <T> Set<T> intersection(Set<T> setA, Set<T> setB) {
Set<T> tmp = new TreeSet<T>();
for (T x : setA)
if (setB.contains(x))
tmp.add(x);
return tmp;
}
public static void main(String args[]) {
String str ="A, B, C, D";
Set<String> set3 = new TreeSet(Arrays.asList(str));
TreeSet<String> set1 = new TreeSet<String>();
TreeSet<String> set2 = new TreeSet<String>();
set1.add("A");
set1.add("B");
set1.add("C");
set1.add("D");
set2.add("A");
set2.add("B");
set2.add("C");
set2.add("D");
System.out.println("Intersection: Set 1 & 2: " + intersection(set1, set2));
System.out.println("Intersection: Set 1 & 3: " + intersection(set1, set3));
}
Comparing a set to another set that I used set.add to add its elments works as expected:
Intersection: Set 1 & 2: [A, B, C, D]
The issue that I can't get my head around is why I don't have a match when I compare a converted TreeSet from a String with another TreeSet.
Intersection: Set 1 & 3: []
But when I print set1 and set3 I find them to be exactly the same??
System.out.println("set1: " + set1);
System.out.println("set3: " + set3);
set1: [A, B, C, D]
set3: [A, B, C, D]
Then I tried looping through the string and added each element to the set but that didn't work either.
System.out.println("Intersection: (set1 - set3)" + intersection(set1, convertString2Set(str)));
private static Set convertString2Set(String line) {
List<String> linesList = new ArrayList<String>(Arrays.asList(line));
Set<String> set = new TreeSet<String>();
for (String elme : linesList) {
set.add(elme);
}
return set;
}
set3 in your code contains only one element: a string which is equal to "A, B, C, D". This string is not equal to either of four strings in set1, which are "A", "B', "C" and "D". The toString() representation of the two sets happens to be the same, but it does not mean that they have the same content.
Arrays.asList() on a String does not split anything; it will always create a single-element list. If you want to split a string into multiple substrings, use the String.split() method.

c# Sorting a object list by combination of three values in the same object

List<string[]> travelerList = new List<string[]>();
string[] traveler1 = {"c","3","b"};
string[] traveler2 = {"a","1","d"};
string[] traveler3 = {"d","4","a"};
string[] traveler4 = {"b","2","c"};
travelerList.Add(traveler1);
travelerList.Add(traveler2);
travelerList.Add(traveler3);
travelerList.Add(traveler4);
I have three columns in a table in Database which will look like
Column1 Column2 Column3
a 1 d
b 2 c
c 3 b
d 4 a
I need to sort the travelerList by combination of above three columns so that after sorting it looks like
{"a","1","d"}
{"b","2","c"}
{"c","3","b"}
{"d","4","a"}
If you can guarantee that the string[] will always have at least 3 elements, you can sort easily enough:
travelerList.OrderBy(t => t[0]).ThenBy(t => t[1]).ThenBy(t => t[2])
Of course, a strongly-typed object is a bit more secure in the matter than a string[]. Something as simple as:
class Traveler
{
public string Column1 { get; set; }
public string Column2 { get; set; }
public string Column3 { get; set; }
}
Then if the list is a List<Traveler> you could be somewhat safer with:
travelerList.OrderBy(t => t.Column1).ThenBy(t => t.Column2).ThenBy(t => t.Column3)
You could even take it a step further and define the object to implement IComparable so that it internally knows how to compare itself with other instances. Then you'd just need:
travelerList.OrderBy(t => t)
This approach would lean more toward object oriented principles, keeping the logic encapsulated within the model so it doesn't need to be repeated by multiple instances of consuming code.
A custom comparator is what you're looking for. Article Here
I'm not sure how this is related to your database since your showing a List<string[]>.
However, ignoring that you can use OrderBy + ThenBy:
travelerList = travelerList
.OrderBy(t => t[0])
.ThenBy(t => t[1])
.ThenBy(t => t[2])
.ToList();

Does Groovy #Canonical work with private fields?

I keep getting a "Could not find matching constructor" when I use #Canonical annotation with private fields. May I know how I can get the following code to compile and pass the asserts? Thanks :)
#groovy.transform.Canonical(includes = ['x','y'])
#groovy.transform.EqualsAndHashCode(includeFields = true)
class Cell implements Comparable<Cell>{
private int x
private int y
int compareTo(Cell cell){
x <=> cell.x ?: y <=> cell.y ?: 0
}
}
Cell cell = new Cell(1,0);
Cell sameCell = new Cell(1,0);
def setOfLiveCells = [] as Set
assert setOfLiveCells.add(cell) // cell is added
assert cell == sameCell // cell equals
assert ! setOfLiveCells.add(sameCell) //should not assert
Regards,
John
Yes, you can do that.
#Canonical is a shorthand for #TupleConstructor #ToString and #EqualsAndHashCode annotations with default values. [code] You can specify them by hand, or simply add necessary annotation before Canonical. #TupleConstructor allows you to set fields, via includeFields or include annotation fields. [doc]
#groovy.transform.TupleConstructor(includeFields = true)
#groovy.transform.Canonical
class Cell implements Comparable<Cell>{
private int x
private int y
int compareTo(Cell cell){
x <=> cell.x ?: y <=> cell.y ?: 0
}
}
Cell cell = new Cell(1,0);
Cell sameCell = new Cell(1,0);
def setOfLiveCells = [] as Set
assert setOfLiveCells.add(cell) // cell is added
assert cell == sameCell // cell equals
assert ! setOfLiveCells.add(sameCell) //should not assert

How do I assign a String at Array1[x] to an int at Array2[x]?

I'm trying to organize data I am given from a text file, there are for 4 pieces of info on each line (City, country, population, and date). I wanted to have an array for each so I first put it all into one big String array and started to separate them into 4 arrays but I needed to change the Population info to an int array but it says *
"Type mismatch: cannot convert from element type int to String"
//Separate the information by commas
while(sc.hasNextLine()){
String line = sc.nextLine();
input = line.split(",");
//Organize the data into 4 seperate arrays
for(int x=0; x<input.length;x++){
if(x%4==0){
cities[x] = input[x];
}
if(x%4==1){
countries[x] = input[x];
}
if(x%4==2){
population[x] = Integer.parseInt(input[x]);
}
if(x%4==3){
dates[x] = input[x];
}
}
}
And when I print out the arrays they have a bunch of nulls in between each data. I'm planning to create objects that have the 4 pieces of data so that I can then sort them by population, dates etc... I'm pretty new to working with objects so if anyone has a better way of getting the 4 pieces of data into an object cause I haven't figured a way yet :/ My end goal was to have an array of these objects that I can u different sorting methods on them
I would recommend doing something like this:
public class MyData {
private String city;
private String country;
private Integer population;
private String date;
public MyData(String city, String, country, Integer population, String date) {
this.city = city;
this.country = country;
this.population = population;
this.date = date;
}
// Add getters and setters here
}
And then in the file you're posting about:
...
ArrayList<MyData> allData = new ArrayList<MyData>();
while(sc.hasNextLine()) {
String[] values = sc.nextLine().split(",");
allData.add(new MyData(values[0], values[1], Integer.parseInt(values[2]), values[3]));
}
...
You need an object to store the data in so that you keep the relationship between the values in each column.
Also, I'm just assuming you're using Java here. Which language we're talking about is something you should include in your question or as a tag.
The problem is with your x index. If you look carefully at your "for" you will see that it will insert a value at every 3 positions.
try
int index = 0;
while(sc.hasNextLine()){
String line = sc.nextLine();
input = line.split(",");
//Organize the data into 4 seperate arrays
for(int x=0; x<input.length;x++){
if(x%4==0){
cities[index] = input[x];
}
if(x%4==1){
countries[index] = input[x];
}
if(x%4==2){
population[index] = Integer.parseInt(input[x]);
}
if(x%4==3){
dates[index] = input[x];
}
}
++index;
}

Resources