I'm new to Hibernate and I'm trying to establish a OneToMany/ManyToOne bidirectional relationship between Person and Vehicle classes. In my example a Person can have many Vehicles and a Vehicle belongs to only one Person. I need a join table: PERSON_VEHICLE with PERSON_ID and VEHICLE_ID as columns and a PERSON_ID column in VEHICLE table. Here's my class design:
Person class:
#Entity
public class Person {
#Id
#GeneratedValue
#Column(name = "PERSON_ID")
private int id;
private String name;
#OneToMany(cascade=CascadeType.ALL, mappedBy="person")
private Collection<Vehicle> vehicleList = new ArrayList<>();
Vehicle class:
#Entity
public class Vehicle {
#Id
#GeneratedValue
#Column(name = "VEHICLE_ID")
private int id;
private String name;
#ManyToOne
#JoinColumn(name="PERSON_ID")
#JoinTable(name="PERSON_VEHICLE", joinColumns=#JoinColumn(name="VEHICLE_ID"),
inverseJoinColumns=#JoinColumn(name="PERSON_ID"))
private Person person;
Here are the DDLs generated by Hibernate.
create table Person (
PERSON_ID integer not null auto_increment,
name varchar(255),
primary key (PERSON_ID)
)
create table Vehicle (
VEHICLE_ID integer not null auto_increment,
name varchar(255),
primary key (VEHICLE_ID)
)
create table PERSON_VEHICLE (
PERSON_ID integer,
VEHICLE_ID integer not null,
primary key (VEHICLE_ID)
)
alter table PERSON_VEHICLE
add index FK_h3d046x5uvbo53p8ms41hwqx (PERSON_ID),
add constraint FK_h3d046x5uvbo53p8ms41hwqx
foreign key (PERSON_ID)
references Person (PERSON_ID)
alter table PERSON_VEHICLE
add index FK_mtm2mn29hel3lbpl6i526w40v (VEHICLE_ID),
add constraint FK_mtm2mn29hel3lbpl6i526w40v
foreign key (VEHICLE_ID)
references Vehicle (VEHICLE_ID)
The VEHICLE table doesn't have PERSON_ID column. Something is wrong but I cannot find what the problem is.
Join table is not required for oneToMany relationship. Only two tables Person and Vehicle is sufficient for this mapping. For detailed example, see This Example
Related
Student entity:
#Entity
#Table(
name = "student"
)
public class Student implements Comparable<Student> {
#Id
#Column(
name = "id"
)
private Integer id;
#Column(
name = "name"
)
private String name;
#OneToOne(cascade=CascadeType.ALL)
#JoinColumn(
name = "id",
referencedColumnName = "student_id"
)
private StudentCard studentCard;
.................................getter and setter below.........................
StudentCard entity:
#Entity
#Table(
name = "student_card"
)
public class StudentCard {
#Id
#GeneratedValue(
strategy = GenerationType.IDENTITY
)
private Integer id;
#Column(
name = "balance"
)
private Integer balance;
....................................getter and setter below.........................
I have two tables created, student and student card. Both tables have a column named id as their primary key, but I am not trying to map them together.
I created a foreign key in the student card table where column student_id is tied with column id from student table. The owner is student card. However, after I created key and annotation, the hibernate still map to the wrong key when I tried to pull out the card information for each student.
For student table, the id is the primary key, whereas the student_id in card table is not. When I call for the student information in the controller side, I get a message of :
Hibernate:
select
studentcar0_.id as id1_1_0_,
studentcar0_.balance as balance2_1_0_,
studentcar0_.student_id as student_3_1_0_
from
student_card studentcar0_
where
studentcar0_.id=?
and this is the wrong map, because I am not mapping student.id=studentcard.id
I tried to switch column/referencecolumn name and it gave me an error of Unknown column 'student_id' not in field list. so I am not sure what should I do at this point.
I'm new to JPA and trying to understand if there's a way to make an Entity where one column is coming from another table that is linked by a foreign key. For example, consider the following tables:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `jobs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11),
PRIMARY KEY (`id`),
CONSTRAINT `fk_jobs_users` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
);
Now I want to make an Entity for the "jobs" table that will include the user.email. I know I can do something like
#Entity
#Table(name = "jobs")
public class JobEntity {
#Id
#Column(name = "id")
private Long id;
#Column(name = "user_id")
private Long userId;
#Formula("(select user.email FROM user WHERE user.id = user_id)")
private String userEmail;
But I feel there's a way I can better leverage the foreign key relationship, but I'm not sure how. I was looking into #JoinColumn but was not seeing the result I wanted since the foreign key is a different column in my Entity. Is there a better way rather than using #Forula to do this?
I don't really understand this. I'm sure #JoinColumn can accomplish the behavior you're looking for.
I was looking into #JoinColumn but was not seeing the result I wanted since the foreign key is a different column in my Entity
Example:
#Entity
#Table(name = "jobs")
public class KronosFileEntity {
#Id
#Column(name = "id")
private Long id;
#ManyToOne
#JoinColumn(name = "user_id", referencedColumn = "id")
private User user;
}
Then you can access the email like job.getUser().getEmail()
Or add a convenience method if that helps
public String getUserEmail() {
return user.getEmail();
}
Then
job.getUserEmail()
I have two entities having parent child relationship - Person and Address.
They have a one-to-one relationship.
I am able to cascade save both of them by one save.
But the below code does not add a foreign_key address_id to Person table.
SQL:
create table PERSON (
id number(20) NOT NULL ,
PRIMARY KEY (id)
);
alter table Person add address_id number(20);
alter table Person add CONSTRAINT FK_Address FOREIGN KEY (address_id) REFERENCES address (id);
create table Address (
id number(20) NOT NULL ,
PRIMARY KEY (id)
);
Hibernate code:
#Entity
#Table(name="Person")
#javax.persistence.SequenceGenerator(name="SOME_SEQ", sequenceName="pk_sequence")
public class Person
{
#Id #GeneratedValue(strategy = GenerationType.SEQUENCE, generator="SOME_SEQ")
private int id;
#OneToOne
#PrimaryKeyJoinColumn
#Fetch(FetchMode.JOIN)
#Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
private Address address;
}
#Entity
#javax.persistence.SequenceGenerator(name="SOME_SEQ", sequenceName="pk_sequence")
public class Address
{
#Id #GeneratedValue(strategy = GenerationType.SEQUENCE, generator="SOME_SEQ")
private int id;
#Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
#OneToOne(mappedBy="address")
#Fetch(FetchMode.JOIN)
private Person person;
}
Driving code:
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
Person p = new Person();
Address add = new Address ();
p.setAddress(add);
add.setPerson(p);
id = (Integer) session.save(p);
tx.commit();
Your mapping is wrong. You have a column in Person that is a foreign key to the address table. But you map the association with #PrimaryKeyJoinColumn, which means: The ID of this entity is also a foreign key to the address table. Use #JoinColumn. Not #PrimaryKeyJoinColumn.
I have 2 tables:
CREATE TABLE `addr1` (
`id` int(11) DEFAULT NULL,
`addr2` varchar(20) DEFAULT NULL
) ENGINE=InnoDB;
CREATE TABLE `address` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`address` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
primary key of addr1 is set from address table. I created my entities using joined inheritance as
#Entity
#Table(name="addr1")
public class Addr1 extends Address {
#Column(name="addr2")
private String addr2;
// getters and setters follows
}
#Entity
#Table(name = "address")
#Inheritance(strategy=InheritanceType.JOINED)
public class Address implements Serializable {
#Id
#GeneratedValue
#Column(name = "id")
private int id;
#Column(name = "address", nullable = false, length = 250, insertable = true)
private String address;
// getters and setters follows
}
Now I have a row in address table with id 2. I want to inset a row in addr1 table with same id (2). I had tried
Address addr = em.getReference(Address.class, new Integer(4));
Addr1 addr1 = new Addr1(addr);
addr1.setAddr2("dsdsd");
em.persist(addr1);
but I am getting an error
javax.persistence.PersistenceException:
org.hibernate.PersistentObjectException: detached entity passed to
persist: Addr1
Please help me.
Regards,
Praveen
It's impossible. Inheritance implies a is-a relationship. Your entity instances can thus be either a bare Address, or an Addr1. And a Java object can't change its type. You can't take an object of type Object, and ask the JVM to change its type and make it an object of type String instead. It's the same here.
If you need to do that, then you should use composition, not inheritance: an Address can have an Addr1. And you should thus have a OneToOne association beteween Address and Addr1, instead of an inheritance relationship.
I have defined a collection in Hibernate like this:
...
public class Item {
...
#ElementCollection
List<Object> relatedObjects;
}
It creates a mapping table with colums item_id and object_id.
The problem is that object_id seems to be unique. In other words I can not have two different items being related to the same object. But that is what I want.
I would like the combination of item_id and object_id to be unique. How do I do that?
That's not what I'm experiencing. For the following entity:
#Entity
public class Person implements Serializable {
#Id
#GeneratedValue
private Integer id;
private String firstName;
private String lastName;
#Enumerated(EnumType.STRING)
private Gender gender;
#ElementCollection
private Set<String> nicknames = new HashSet<String>();
private String dept;
// getters, setters
}
The following tables get created:
create table Person (id integer generated by default as identity, dept varchar(255), firstName varchar(255), gender varchar(255), lastName varchar(255), primary key (id))
create table Person_nicknames (Person_id integer not null, nicknames varchar(255))
alter table Person_nicknames add constraint FK24F0D97B19ACB65E foreign key (Person_id) references Person
There is no unique constraint. But I can't say more without seeing your "Object" class (it's an embeddable class, right?).
PS: ElementCollection can't be a ManyToMany, this is more a OneToMany.