Sorry if my post is duplicated or the tittle doesn't describe the topics, because I don't know how to describe this in the tittle, I look on internet, but I didn't find the solution.
I am using Java and JPA. The problem is the next :
I have a class A with an autogenerated key :
class A{
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private List<B> listB;
}
And the class B with the id of this clas:
class B {
#EmbeddedId
private Bid id;
private String att;
}
class Bid {
private int idA;
private String text;
}
In a controller I want to create an object A, the problem is when I created the object A, I need to create the object B where the id of B contains the id of A which is autogenerated, and it is created in the moment when the entity is mapped to de database, I dont't know how to set the id autogenerated of A into the idB, maybe I should query to de database asking what is the las id of classA, but it seem bad.
Thanks in advance
Your case is a derived identifier case, where your entity B's identity was derived from the primary key of A. You can use #MapsId annotation for this case and your entities can be restructured like this:
#Entity
public class A {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#OneToMany(mappedBy="a")
private List<B> listB = new ArrayList<B>();
...
}
#Entity
public class B {
#EmbeddedId
private BId id;
#ManyToOne
#MapsId("idA")
private A a;
...
}
#Embeddable
public class BId {
private int idA;
private String att;
...
}
This is how you would persist the entities:
A a = new A();
BId bid = new BId();
bid.setAtt("text"); // notice that the idA attribute is never manually set, since it is derived from A
B b = new B();
b.setId(bid);
b.setA(a);
a.getListB().add(b);
em.persist(a);
em.persist(b);
See sample implementation here.
It would be useful to know which is the case scenario you are trying to solve in general because the structure you are using seems unnecessarily complex.
What is your real goal?
Related
I'm having three entities which are being saved into the DB. For instance we have 3 entities A, B and C. A is having OneToOne mapping with B and ManyToOne mapping with C which is uni-directional.
public class A {
#Id
#GeneratedValue
private int id;
private String number;
//Other fields declared
#PostPersist
private void onSaving(){
number = "STU" + id;
}
}
public class B {
#Id
#GeneratedValue
int otherID; //primary key for B
//Other fields declared
#OnetoOne(targetEntity = A.class, cascade= CascadeType.ALL)
#JoinColumn(name = "id") // id is the primary key of class A
private A a;
}
public class C {
#Id
#GeneratedValue
int otherID; //primary key for C
//Other fields declared
#ManytoOne
#JoinColumn(name = "id") // id is the primary key of class A
private A a;
}
Below is the service class for the above entities
#Service
public class testService {
#Autowired
private BRepo bRepo; // BRepo is the interface which is extending the JPARepository.
#Autowired
private CRepo cRepo; // CRepo is the interface which is extending the JPARepository.
#Transactional
public A saveEntity(B b, List<C> c) {
bRepo.save(b);
cRepo.saveAll(c);
return b.getA();
}
}
The entity fields/data are getting perfectly saved into the DB, the only issue I'm facing is with the #PostPersist annotation. My requirement is when save is performed, the number field/variable of entity A should be saved as "STU" + id(primary key for A), but in the DB it is saving as STU0 every time I perform save.
I'm unable to find the root cause for this over the internet. Requesting you to please help me debug this issue. Thank you.
The issue got resolved after I added, strategy as IDENTITY
#GeneratedValue(strategy = GenerationType.IDENTITY)
I have to join two tables and filter the result with a Where with Specifications and JPA. But I'm not very familiar with it.
The tables are for example:
public class A {
private Long id;
private Long secondId;
...
}
public class daughterA {
#JoinColumn (name = "id")
private Long idA;
...
}
and the WHERE is to be applied on secondId.
Thank you all for the help, I apologize for any inaccuracies, i'm beginning with these technologies.
First of all, your Join seems to be a one To Many join so you should make it as it is :
add the One annotation in the parent class being mapped by the name of the instance of it in the other class, this notation covers a Set or a List of objects of the daughters class
add the ManyToOne annotation in the daughter class, a daughter can only have one mother, and idA is not Long but it refers to the parent class it's in fact a foreign key
public class A{
#Id
private Long id;
private Long secondId;
#OneToMany(mappedBy="idA")
private Set<daughterA > daughters;
...
}
public class daughterA {
#ManyToOne
#JoinColumn (name = "id")
private A idA;
...
}
and for the where clause :
TypedQuery<Country> query =
em.createQuery("SELECT d FROM daughterA d WHERE d.idA.secondId = :secondId ", Country.class);
A results = query.setParameter("secondId",sencondId).getSingleResult();
How do I implement one-many relationship in ORMLite Android?
please find the example
public class A {
private String name;
#DatabaseField (foreign = true, foreignAutoRefresh = true, columnName = "A")
private B b;
#DatabaseField(columnName = "author")
private String authorName;
}
public class B {
#DatabaseField(generatedId = true, columnName = "id")
private long id;
#DatabaseField(columnName = "name")
private String name;
#ForeignCollectionField
Collection<A> aees;
}
B has collection of A. I am calling dao.create(b);
Now i create dao of b, since b has all the data. But the table B has only created with data, A is never created. Kindly could some one help?
Now i create dao of b, since b has all the data. But the table B has only created with data, A is never created. Kindly could some one help?
Right. You need to create the A items using:
for (A a : b.aees) {
aDao.create(a);
}
ORMLite does not automatically create those for you.
You might take a look a the source code of the foreign-collection example program.
You have to override the DAO of the B class, so when an object B is created or updated, the objects in the collection to be also updated.
Take a look at this question: Collections in ORMLite.
i was facing the same problem. My json was like:
{
"parent":{
"name":"ABC",
"children":[
{"childName":"1"},
{"childName":"2"},
{"childName":"3"}
]
}
}
i resolved the issue like this:
Parent parent = new Parent();
parent.setName("ABC");
while(get children one by one from json data)
{
childrenArray.add(new Child(its Name));
}
parentDAO.create(parent);
for(Child child : childrenArray)
{
child.setParent(parent);
childDAO.create(child);
}
I encountered a problem with lazy association two days ago and still haven't found an explanation of such a behavior.
Here is my simplified class hierarchy:
#Entity
#Table(name="A")
public class A
{
#Id
#GeneratedValue
#Column(name="ID")
private int id;
#OneToMany(mappedBy="a", fetch=FetchType.LAZY, cascade=CascadeType.ALL)
private Set<B> listB = new HashSet<B>();
}
#Entity
#Table(name="B")
public class B
{
#Id
#GeneratedValue
#Column(name="ID")
private int id;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="A_ID")
private A a;
#ManyToOne(fetch=FetchType.LAZY) // ERROR!
// #ManyToOne(fetch=FetchType.EAGER) // OK
#JoinColumn(name="C_ID")
private C c;
}
#Entity
#Table(name="C")
public class C {
#Id
#GeneratedValue
#Column(name="ID")
private int id;
}
When I try to read simple structure from db: A->B->C i get the following results:
System.out.println(a.getId()); // 1
for (B b : a.getListB()) {
System.out.println(b.getId()); // 1
C c = b.getC();
System.out.println(c.getId()); // 0 !!!
}
As you can see instance of C is not properly initialized.
After changing fetch type from LAZY to EAGER for field c in class B everything works!
I suspect there is is some CGLIB magic, but can't find a clue nether in the specification nor in Google.
Could someone explain this?
Thanks for any help!!!
In case you would like to understand lazy loading see this answer; it defines it pretty well.
Fixed. My question was not correct. Sorry.
There was final modifier for getters and setters of my entitiy classes. It breaks single value associations like many-to-one.
Suppose I've missed some warnings in hibernate logs...
I think it would be better to throw an exception by hibernate for this case.
I am using hibernate annotations in my application. But I am getting one problem.
class A
#Entity
#Table(name = DBConstants.T_A )
#Inheritance(strategy=InheritanceType.JOINED)
public class A {
//Id
#Column(name = "id")
#GeneratedValue(generator = A_SEQ)
#SequenceGenerator(name = A_SEQ, sequenceName=SeqA_SEQ)
private long id;
....
}
class B
//Entity
#Table(name = "T_B")
#PrimaryKeyJoinColumn(name = "a_id")
public class B extends A{
String a;
.....
}
class C
#Entity
#Table(name = "T_C")
#PrimaryKeyJoinColumn(name = "a_id")
public class C extends B
{
...
}
Initially, I am saving the class A.
After some time, while saving class C, I set Class A id which was saved already. While trying to save the class C, it creates a new class A object and sets that newly created object value to class C object. I needed the class C object with class A object id which is created at first.
I don't understand why a new object of class A is created again. Can anyone please answer to my question what went wrong?
Since you want C to have the same id as an object A that already exists, this is not really entity inheritance.
You basically want a reference to an existing object and you should be using a #OneToOne relationship to map this.