I have a class A with setters and getters
class A{
private int id;
private List<B> b;
}
I want to fetch the A object based on the B objects. So suppose I have a list of B objects I want to get the A objects that contain the B.
So i decided to use in
Here is the code
Criteria criteria = session.createCriteria(A.class).setCacheable(false);
criteria.add(Restrictions.in("b",{list of B})).list();
This gives an error java.sql.SQLException: No value specified for parameter 1
How can I get object A using B
You should join the B's first:
Criteria criteria = session.createCriteria(A.class)
.setCacheable(false)
.setFetchMode("bList", FetchMode.JOIN)
.createAlias("bList", "b");
and then use an IN for the ids of b:
criteria.add(Restrictions.in("b.id",{list of B})).list();
Set your fetch mode accordingly whether you want the list of B's also apart from A.
First of all I've been all the morning seeking for a solution for my problem. I've found similar problems but no one fixed my problem :(
I have a 3 level inheritance on my Java classes model:
A <-- B <-- C
Mapping this into a Relational Data Base I've made
A (1) -- (0..1) B (1) -- (0..1) C, so my annotated Java classes are something like:
#Entity
#Inheritance(strategy=InheritanceType.JOINED)
#DiscriminatorColumn(name="type", discriminatorType=DiscriminatorType.INTEGER)
#XmlRootElement
public class A implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long idA;
private Integer type;
...
}
#Entity
#DiscriminatorValue("2")
#PrimaryKeyJoinColumn(name="idB", referencedColumnName="idA")
#XmlRootElement
public class B extends class A implements Serializable{
private Long idB;
private Integer type;
#OneToOne(cascade={CascadeType.REMOVE}, fetch=FetchType.LAZY)
#JoinColumn(name = "idB")
private A a;
...
}
#Entity
#DiscriminatorValue("8")
#PrimaryKeyJoinColumn(name="idC", referencedColumnName="idB")
#XmlRootElement
public class C extends class B implements Serializable{
private Long idC;
#OneToOne(cascade={CascadeType.REMOVE}, fetch=FetchType.LAZY)
#JoinColumn(name = "idC")
private B b;
...
}
I don't know why, invoking a Query SELECT c FROM C c retrieves me 0 result when I have info on that table. If I do the query SELECT b FROM B b it works fine. It seems to be something wrong with the hierarchy annotations I've used.
Any idea? Thank you in advance :)
Joined table inheritance means that when you have a C entity, there must be a row in the A, B AND C tables. If you have data in C but no corresponding data in A or B that match up, then you will get no C entities back - the data is invisible to JPA because it first queries the A table to see if there are rows with a Type=3, and then joins it to B and C.
So check that your java inheritance model actually matches the data model. You also show that B and C have a reference to their parent - this cause the same id field to be mapped twice, as it is in both the Entity's PrimaryKeyJoinColumn and the mapping's JoinColumn. Since the referenced A (or B) is apart of the B (or C), there is no need to also have an object referenence to it - any of the inherited get methods will return the data from the A table anyway.
Consider the following scenario:
(The following things have been omitted: Constructors, Getters and Setters, #Column annotations, #Basic annotations, #Table annotations, imports and package declarations. The rest is EXACTLY as I intend it to be (even empty annotations))
#Inheritance(strategy=InheritanceType.JOINED)
#Entity
public class A {
#Id #GeneratedValue
private long id;
private String aValue;//There are getters and setters for this, but I omitted them
}
#Entity
public class B extends A {
private String bValue;
}
//Missing #Inheritance here - JPA2 says "default" #Inheritance if it is missing
//But what does that mean?
#Entity
public class C extends A {
private String cValue;
}
#Entity
public class D extends C {
private String dValue;
}
//Missing strategy, whose default, according to the annotation interface, is SINGLE_TABLE
#Inheritance
#Entity
public class E extends C {
private String eValue;
}
#Entity
public class F extends E {
private String fValue;
}
#Entity
public class G extends E {
private String gValue;
}
Quick summary of the classes without the syntax:
A (#Inheritance(strategy=InheritanceType.JOINED)
B, C (no annotation)
D, E (#Inheritance)
F, G
If you were to follow JPA's spec, should there be
A: tables for A, B, C, D, E, F and G, all containing id + classValue
B: tables for A, B, C, D and {EFG}, with A, B, C & D containing id + classValue, and {EFG} containing id + eValue + fValue + gValue + DTYPE
C: tables for A, B and {CDEFG}, with A and B containing id + classValue, and {CDEFG} containing id + cValue + dValue + eValue + fValue + gValue + DTYPE
Or is it some other scenario I haven't thought of yet?
I would test it, but I'm not sure whether it would be the implementation of JPA or the specification itself filling in the blanks of "What happens when an #Inheritance annotation is not missing, but has an undefined strategy"?
Personally I'm pretty sure C won't happen, but I don't know whether it will map like A or B.
Hence the question title:
Does #Inheritance default to "SINGLE_TABLE" (no matter whether it's missing or undefined), or does it default to "fallthrough" (check how the entity hierarchy above deals with things) and if that's not possible, "SINGLE_TABLE"? And what if the annotation is there, but doesn't have a strategy defined?
I think the correct answer is "It depends on your Implementation". From the JSR spec (JSR317 ยง2.12 "Inheritance Mapping Strategies"):
Support for the combination of inheritance strategies within a single entity inheritance hierarchy is not required by this specification.
In this case, the root of your hierarchy is A, with JOINED explicitly specified so then you'd have tables for each entity.
Now if your JPA implementation supported multiple inheritance types per hierarchy, judging from the Javadoc and Source of the annotation, I would personally expect there to be tables for A, B, C, D, {EFG}
As you point out, if the annotation is present, the strategy is SINGLE_TABLE unless explicitly specified. As the Javadoc and the Spec refer to the treatment of #Inheritance in terms of class hierarchies, I would think that if the current class does not have the annotation, I look to the parent and up the tree until I either find an annotation, or I reach the root of the class hierarchy (and default to SINGLE_TABLE)
For me it is not 100% clear, does following in JPA 2.0 specification
Support for the combination of inheritance strategies within a single entity
inheritance hierarchy is not required by this specification.
mean that:
if implemented, should honor all other constraints presented (most
likely) or
if implemented, can relax other constraints presented.
Luckily reference implementation has chosen first option. With EclipseLink #Inheritance without argument defaults to single table and not having #Inheritance annotation at all honours #Inheritance annotation found from the superclass (does not have to be immediate superclass). These entities will be mapped to five tables:
A: id dtype avalue
B: id bvalue
C: id cvalue
D: id dvalue)
E: id evalue, fvalue, gvalue
(B-E id being FK to A id)
Persisting entities works as expected, each entity is saved to tables of superclasses as well without problems.
you need to add inheritanse annotation with discriminator parameter to see all info about this stuff just visit [a link]http://www.java2s.com/Code/Java/JPA/SetDiscriminatorValue.htm
I have 2 test classes:
Class A{
B b;
// some other properties
}
Class B{
// some properties
}
every instance of A has only one instance of class B, but an instance of class B can be assigned to more than one instance of class A
like :
B b = new B();
A a1 = new A();
a1.setB(b);
A a2 = new A();
a2.setB(b);
what type of association is this?
At first I was thinking about a one-to-one unidirectional but maybe is a many-to-one? but I don't have any collection of A objects on B.
Can someone explain me what is the correct way to implements this association (using annotation)?
every instance of A has only one instance of class B, but an instance
of class B can be assigned to more than one instance of class A
So , A to B is the many-to-one relationship . B to A is the one-to-many relationship.
The following shows the bi-directional mapping between A and B using annotation:
#Entity
#Table(name="tableA")
Class A{
#ManyToOne
#JoinColumn(name = "B_ID")
B b;
// some other properties
}
#Entity
#Table(name="tableB")
Class B{
#OneToMany(mappedBy = "b")
List Set<A> listOfA= new ArrayList<A>();
// some other properties
}
Important points:
#Entity marks the java class as an hibernate entity. It is mapped to the name of the table specified in the #Table
If no #Table is specified ,by default , it is mapped to the table with the name that is equal to the unqualified class name of the entity.
#ManyToOne defines Class A to Class B 's relationship is many-to-one
In the relational database , one-to-many relationship is expressed by using the following foreign key constraint :
"Many side table" has a FK column which only accepts the PK of the "one side table".
This name of this FK column can be defined explictly by the name attribute of #JoinColumn. If #JoinColumn is not specified , then default value(s) with be used for this FK column , which concatenates with the name of "one side table", _ (underscore), and the name of the PK in the "one side table".
#OneToMany defines Class B to Class A 's relationship is one-to-many.
The relationship is:
B (One) ---to--> A (Many)
Given a class:
class MyClass {
private String a;
private String b;
private String c;
}
and code like so:
Query q = getEntityManager()
.createNativeQuery('select a, b from table', MyClass.class);
It throws an exception. My solution is to add
'' as c
in the sql. However, the c in MyClass is a variable that I intend to put some calculated value into, and that c does not have any real mapping to the table, so the solution just puts the c with a blank value...
My question is, are there any alternatives?
You need to mark c as #Transient so that it is not mapped.