Reputation: 907
I have 2 entities Customer and Address, the relationship is an address can belong to multiple customers.
Below is the customer class as you can see it has an reference to the address object, in the underlying customer table it is the id of the address. I have omitted getters and setters as well as some simple variables.
@Entity
@Table(name = "customer")
public class Customer implements Serializable {
@Id
@GeneratedValue
@Column(name = "customer_id")
private int customerId;
@ManyToOne
@JoinColumn(name = "store_id")
private Store store;
@ManyToOne
@JoinColumn(name = "address_id")
private Address address;
........
}
Below is the address class.
//Address Class
@Entity
@Table(name = "address")
public class Address implements Serializable {
@Id
@GeneratedValue
@Column(name = "address_id")
private int addressId;
@JoinColumn(name = "city_id")
@ManyToOne
private City city;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "address")
@JsonIgnore
List<Customer> customers;
......
}
I have tried persisting a new customer and a new address in a single call to persist like below. I have omitted some variables i set.
Customer cus = new Customer();
Address addr= new Address();
........
cus.setAddress(addr)
List<Customer> cusList= new ArrayList<>();
cusList.add(cus);
addr.setCustomers(cusList);
entityManager.persist(cus)
But i get an error saying the address_id in the customer table is null . I would have thought the JPA would have inserted the new address and then inserted the new customer with the address id column set to the new address id? Is my thinking here wrong? Or have i made a mistake in the mapping or how i am persisting the entities?
Another way i could do this is persist address first and then persist customer but would prefer to do it in a single persist if possible.
Below are the underlying tables.
//Customer Table
CREATE TABLE `customer` (
`customer_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`store_id` tinyint(3) unsigned NOT NULL,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`email` varchar(50) DEFAULT NULL,
`address_id` smallint(5) unsigned NOT NULL,
`active` tinyint(1) NOT NULL DEFAULT '1',
`create_date` datetime NOT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`customer_id`),
KEY `idx_fk_store_id` (`store_id`),
KEY `idx_fk_address_id` (`address_id`),
KEY `idx_last_name` (`last_name`),
CONSTRAINT `fk_customer_address` FOREIGN KEY (`address_id`) REFERENCES `address` (`address_id`) ON UPDATE CASCADE,
CONSTRAINT `fk_customer_store` FOREIGN KEY (`store_id`) REFERENCES `store` (`store_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=608 DEFAULT CHARSET=utf8;
/Address Table
CREATE TABLE `address` (
`address_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`address` varchar(50) NOT NULL,
`address2` varchar(50) DEFAULT NULL,
`district` varchar(20) NOT NULL,
`city_id` smallint(5) unsigned NOT NULL,
`postal_code` varchar(10) DEFAULT NULL,
`phone` varchar(20) NOT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`address_id`),
KEY `idx_fk_city_id` (`city_id`),
CONSTRAINT `fk_address_city` FOREIGN KEY (`city_id`) REFERENCES `city` (`city_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=619 DEFAULT CHARSET=utf8;
Thanks.
Upvotes: 0
Views: 62
Reputation: 19956
If you want to save a new Address
with a Customer
you need to add CascadeType.ALL
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id")
private Address address;
And save all by this way (you don't need to add a customer to the address list because a customer refer to the address just by a foreign key address_id
)
Customer cus = new Customer();
Address addr = new Address();
cus.setAddress(addr)
entityManager.persist(cus)
But this is not a very convenient way because of addresses are something like reference. So it is unusual to update address in reference by saving every customer.
Upvotes: 1