table: emps
(
id int primary key,
name varchar(50)
);
table: emps_sal
(
emps_sal_id int primary key auto_increment,
ids int,
salary int,
foreign key(ids) references emps(id)
);
Entity Classes:
#Entity
public class Emps {
#Id
#Column(name="id")
int id;
String name;
#OneToOne(mappedBy = "e")
Emps_sal esal;
--
}
#Entity
public class Emps_sal {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
int emps_sal_id;
int ids ;
int salary;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn(name="ids")
Emps e;
--
}
Now when I am doing simple select query its working fine. But when I am trying to add entry its working weirdly:
Emps e=new Emps();
e.setId(100);
e.setName("Johnson");
Emps_sal es=new Emps_sal();
es.setIds(100);
es.setSalary(5000);
es.setE(e);
e.setEsal(es);
Firstly in "emps" table it added a extra column "esal_emps_sal_id".
Though it added "100,Johnson" properly. But in Emps_sal nothing is
added. I was expecting "7, 100, 5000".
Change CascadeType to persist in Emps_sal entity class
#OneToOne(cascade = CascadeType.PERSIST)
#PrimaryKeyJoinColumn(name="ids")
Emps e;
The persist operation makes a transient instance persistent. CascadeType PERSIST propagates the persist operation from a parent to a child entity. When we save the Emps_sal entity, the Emp entity will also get saved.
Here is how you need to set the data
Emps e=new Emps();
e.setId(100);
e.setName("Johnson");
Emps_sal es=new Emps_sal();
es.setIds(100);
es.setSalary(5000);
es.setE(e);
entityManager.persist(es);
Related
My model (exemplified) is the following:
CREATE TABLE person (
id INT PRIMARY KEY,
name TEXT
...
);
CREATE TABLE team (
id INT PRIMARY KEY,
name TEXT
....
);
CREATE TABLE team_reference_persons (
team_id INT NOT NULL,
person_id INT NOT NULL,
uses_telephone BOOLEAN,
PRIMARY KEY (team_id, person_id),
FOREIGN KEY (team_id) REFERENCES team(id),
FOREIGN KEY (person_id) REFERENCES person(id)
);
And my JPA defintion:
#Entity
#Table(name = "team")
public class Team {
#Id
private Integer id;
#OneToMany
#JoinTable(name = "team_reference_persons", joinColumns = #JoinColumn(name = "team_id", referencedColumnName = "id"), inverseJoinColumns = #JoinColumn(name = "person_id", referencedColumnName = "id"))
private List<Person> teamReferencePersons;
...
}
#Entity
#Table(name = "person")
public class Person {
#Id
private UUID id;
private String name;
...
}
So far, so good, when all you need is the person list on the team. But now I need to add the team_reference_persons.uses_telephone property from the join table in my person domain, So I am looking for a way to keep the persons logic, while I create a new subclass.
private class TeamIndividual extends Person {
boolean uses_telephone;
}
Then changing List<Person> on Team entity by List<TeamIndividual>. Is that possible someway? JPA should be indicated in such smart way that it adds the join table property to the final target entity (on both read and save).
No need to extend TeamIndividual to Person.
Annotate TeamIndividual with #Table(name = "team_reference_persons")
Define fields(teamId,personId,uses_telephone) inside TeamIndividual
Annotate fields teamId and PersonId with #ManyToOne and #JoinColumn
Add List to Team without annotation
Try this,It will work..!!
I want to store Persons with their Cars in the database. I use Spring 5.
The problem is that when I want to add a person with cars in the database, the 'person_id' field from the 'car' table is set to null instead of being set on the id of the created person.
That is weird because I even set that nullable=false in Car class.
#Entity
public class Person {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer id;
#OneToMany(mappedBy = "person",cascade = CascadeType.ALL)
List<Car> cars;
}
#Entity
public class Car {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer carId;
#ManyToOne
#JoinColumn(name = "person_id",nullable=false)
private Person person;
}
CREATE TABLE person (
id INT PRIMARY KEY AUTO_INCREMENT,
...
);
CREATE TABLE car (
id INT PRIMARY KEY AUTO_INCREMENT,
person_id INT,
ADD CONSTRAINT person_id REFERENCES person(id)
);
I use the JpaRepository to save a person:
Person p = new Person();
List<Car> cars = new ArrayList<>();
Car c1 = new Car();
Car c2 = new Car();
cars.add(c1);
cars.add(c2);
p.setCars(cars);
personJpaRepository.save(p);
If you want to take advantage of the Cascade option you must remember to set the dependencies on both sides of the relationship.
Otherwise the persistence provider will not consider that as a relationship:
cars.add(c1);
cars.add(c2);
c1.setPerson(p);
c2.setPerson(p);
p.setCars(cars);
personJpaRepository.save(p);
I have the following relationship with person and transaction (one to one in my case). I want to be able to save a Person with a Transaction attached resulting in two inserts. One in tbl_person and one in tbl_Transaction. But the following only generates one insert instead of two. The one insert is in tbl_Transaction:
`CREATE TABLE `tbl_person` (
`ID` char(36) NOT NULL,
`TransactionID` int(11) DEFAULT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `TransactionID` (`TransactionID`),
CONSTRAINT `tbl_person_ibfk_1` FOREIGN KEY (`TransactionID`)
REFERENCES `tbl_Transaction` (`TransactionID`)
);
CREATE TABLE `tbl_transaction` (
`TransactionID` int(11) NOT NULL,
PRIMARY KEY (`TransactionID`)
);
#Table(name="tbl_person")
#Entity
#JsonIgnoreProperties(ignoreUnknown = true)
#ToString
#Data
public class Person {
#Id
#GeneratedValue(generator = "hibernate-uuid")
#GenericGenerator(name = "hibernate-uuid", strategy = "uuid2")
#Column(name="ID", nullable = false)
private String ID;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "transactionId")
private Transaction transaction;
}
#Table(name="tbl_transaction")
#Entity
#Data
public class Transaction {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer transactionId;
}
public class Service() {
public void saveTransaction(Transaction transaction) {
Person person = new Person();
person.setTransaction(transaction);
getSessionCurrent().save(person);
}
}
`
service.saveTransaction(transaction);
The service.saveTransaction returns with no exception but it only inserts the transaction but not the person.
Can any one tell me what I am doing wrong ??
you need to define a #OneToOne field in Transaction class
like specified in this question:
#OneToOne bidirectional mapping with #JoinColumn
and then add this line:
transcation.setPerson(person);
I need to map a OneToMany relationship in hibernate, with the JPA annotations, in which is involved a weak entity.
For example
Table orders:
CREATE TABLE orders(
idorder serial NOT NULL,
note varchar(30),
CONSTRAINT orders_pkey PRIMARY KEY (idorder)
)
Table OrderItems:
CREATE TABLE orderitems(
idorder integer NOT NULL,
iditem serial NOT NULL,
qnt integer,
CONSTRAINT orderitems_pk PRIMARY KEY (idorder, iditem),
CONSTRAINT fk_orderitems FOREIGN KEY (idorder)
REFERENCES orders (idorder) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
Within my class "Orders" I have realized the method getOrderItem() in this way:
// i need cascadeType.All here
#OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "order")
public Set<OrderItem> getOrderItems() {
return items;
}
now,
not being able to know the identifier that will be assigned to a new order
prior to insertion, such as Annotations can I use within the class OrderItem in order to submit automatically (in cascade mode) the correct idOrder?
my goal is to get a situation like this.
Order myOrder = new Order();
// myOrder.setId(1) not necessary
myOrder.setNote("orderNote");
OrderItem firstItem = new OrderItem();
// firstItem.setIdOrder() no need to specify idorder
// firstItem.setId(12);
firstItem.setName("firstItem");
firstItem.setQnt(2);
OrderItem secondItem = new OrderItem();
// secondItem.setId(13);
secondItem.setName("secondItem");
secondItem.setQnt(4);
Set<OrderItem> items = new HashSet<OrderItem>();
items.add(firstItem);
items.add(secondItem);
myOrder.setItems(items);
OrderDAO dao = new OrderDAO();
dao.save(myOrder); // i want inser all items in cascade with the idOder assigned to "myOrder"
Ok I will try to add Entity classes you need to have above given scenario.
#Entity
#Table(name="orders")
public class Order{
#Id
#GeneratedValue
#Column(name="ID")
private Long id;
#Column(name="note ")
private String note ;
#OneToMany(mappedBy="orders")
private Set<OrderItem> orderitems;
// Getter and Setter methods
}
And then the OrderItem class
#Entity
#Table(name="OrderItems")
public class OrderItem{
#Id
#Column(name="iditem")
private Long iditem;
#Column(name="qnt")
private long qnt ;
#ManyToOne
#JoinColumn(name="idorder")
private Order order;
public OrderItem() {
}
// Getter and Setter methods
}
Also i dint get which column your setname maps to.. and iditem isnt generated value its assigned id type
Ok then it also could be issue about inverse that who could be the relationship owener .. Inverse=true is same behaviour as mappedBy attribute usage so try changing it..
Let me know if this works or you get a issue while trying this out..
This is the code:
#Entity
public class Dept {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#OneToMany(
mappedBy = "dept",
cascade = CascadeType.ALL
)
private List<Employee> employees = new ArrayList<Employee>();
public void addEmployee(Employee emp) {
this.employees.add(emp);
}
}
#Entity
public class Employee {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
#Column private Integer age;
public Employee(Integer a) {
this.age = a;
}
}
Then in a unit test I'm doing this (OpenJPA is used):
// ...
Dept dept = new Dept();
dept.addEmployee(new Employee(25));
this.em.persist(dept);
OpenJPA says:
Caused by: <openjpa-1.2.1-r752877:753278 nonfatal general error>
org.apache.openjpa.persistence.PersistenceException: Attempt to insert
null into a non-nullable column: column: ID table: EMPLOYEE in
statement [INSERT INTO employee (age) VALUES (?)]
{prepstmnt 841687127 INSERT INTO employee (age) VALUES (?)
[params=(int) 25]} [code=-10, state=23000]
Why ID is not auto-generated?
You one-to-many relationship is mapped as bidirectional (due to mappedBy), but I can't see the other side. Perhaps it's the cause.
And even if many-to-one side actually exists, it's not initialized in your code though it's an owning side of the relationship, therefore it specifies the state to be reflected in the database.
If you actually mean unidirectional relationship, you need to remove mappedBy.