OneToOne with the same PrimaryKey and ForeignKey - java

Database
*user_account*
id (PK)
email
password
*user_detail*
id(PK)(FK)
name
city
Entities
#Table(name="user_detail")
public class UserDetail implementsSerializable{
#Id private Integer id;
...
#OneToOne
#JoinColumn(name="id")
private UserAccount userAccount;
}
#Table(name="user_account")
public class UserAccount implementsSerializable{
#Id private Integer id;
#OneToOne(mappedBy="userAccount")
private UserDetail userDetails;
}
Error
Exception Description: Multiple writable mappings exist for the field [user_detail.ID]. Only one may be defined as writable, all others must be specified read-only.

If the ID in UserAccount is both a primary key and a foreign key, then you should declare it as a single field and map it appropriately. Like this:
#Entity
public class UserAccount implements Serializable {
#Id
#OneToOne(mappedBy="userAccount")
private UserDetail userDetails;
}
Or else using #MapsId.
However, i suspect that what you really want is a single class spread over two tables:
#Entity
#Table(name = "user_account")
#SecondaryTable(name = "user_detail")
public class User implements Serializable {
#Id
private int id;
private String email;
private String password;
#Column(table = "user_detail")
private String name;
#Column(table = "user_detail")
private String city;
}

You cannot have both #Id private Integer id; and #JoinColumn(name="id"), you must remove one of them: I doubt that you really need a primary key in the details, so just remove the #Id line from there.

Related

One-to-One association with composite ID of owner Entity

I have a to make a one-to-one association between two Entities, but one of them must have two #Id. One is PRI another one is MUL. How must i declare composite id, and how do i need to map the classes?
#Entity
#Table(name = "PERSONS")
public class Person implements Serializable{
private static final long serialVersionUID = -3451407520028311143L;
#Id
#Column(name = "ID")
private Integer id;
#Column(name = "ADDRESS_ID")
private Integer addressId;
#Column(name ="NAME")
private String name;
#OneToOne(mappedBy= "person", cascade= CascadeType.ALL)
private Address address;
...
}
second class is mapped via #IdClass annotation
#Entity
#Table ( name = "ADDRESS" )
#IdClass(AddressKeys.class)
public class Address implements Serializable {
#Id
#Column ( name = "ID")
private Integer id;
#Id
#Column ( name = "PERSON_ID")
private Integer idPerson;
#Column ( name = "CITY" )
private String city;
#OneToOne(cascade= CascadeType.ALL)
#JoinColumn(name="PERSON_ID")
private Person person;
...
}
and the id class
class AddressKeys implements Serializable{
private Integer id;
private Integer idPerson;
//getters and setters
#Override
public int hashCode() {
...
return result;
}
#Override
public boolean equals(Object obj) {
...
}
}
So when i try to create and save a record i have a next error
Could not open sessionRepeated column in mapping for entity:
hibernateMappedModels.base1.mappedClasses.oneToOne.Address column:
PERSON_ID (should be mapped with insert="false" update="false")
java.lang.NullPointerException at
hibernateMappedModels.base1.Main.run(Main.java:45) at
hibernateMappedModels.base1.Main.main(Main.java:24
I tryed to make an Id fields unInsertable and unUpdatable, and it was working, but i need them to be insertable and updatable; Is there any possibility to do it?
I am confused by your mappings and not sure what is required other then the simple mappings below: if I am missing something then you will need to expand on your question. You are getting the error as you have mapped the column twice - once via the one-to-one and once as a simple property. Additionally, I am not sure why you require a composite key on address.
#Entity
#Table(name = "PERSONS")
public class Person implements Serializable{
private static final long serialVersionUID = -3451407520028311143L;
#Id
#Column(name = "ID")
private Integer id;
#Column(name ="NAME")
private String name;
#OneToOne(mappedBy= "person", cascade= CascadeType.ALL)
private Address address;
}
#Entity
#Table ( name = "ADDRESS" )
public class Address implements Serializable {
#Id
#Column ( name = "ID")
private Integer id;
#Column ( name = "CITY" )
private String city;
#OneToOne(cascade= CascadeType.ALL)
#JoinColumn(name="PERSON_ID")
private Person person;
}

How to adjust relations between entities using Hibernate mapping?

I have such a simple scheme
and the following entities:
#Entity
public class Ticket {
#Id
#GeneratedValue
private Integer id;
#ManyToOne
private Event event;
#OneToOne
private User user;
#Embedded
private Seat seat;
private TicketState state;
private Float price;
// getters, setters, etc.
#Entity
public class Event {
#Id
#GeneratedValue
private Integer id;
#OneToOne
private Movie movie;
#Embedded
private Auditorium auditorium;
private LocalDateTime startDateTime;
#OneToMany
private Set<Ticket> tickets = new HashSet<>();
// getters, setters, etc.
#Entity
public class User {
#Id
#GeneratedValue
private Integer id;
#Enumerated(EnumType.STRING)
private UserRole role;
private String name;
private String email;
private Instant birthday;
#OneToMany
private List<Ticket> tickets = new ArrayList<>();
private boolean lucky;
// getters, setters, etc.
#Embeddable
public class Auditorium {
private Integer id;
private String name;
private Integer seatsNumber;
#ElementCollection
private List<Integer> vipSeats;
// getters, setters, etc.
Also these entities was added to hibernate.cfg.xml.
Than I run app I have the following exception:
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.epam.spring.core.domain.Event column: id (should be mapped with insert="false" update="false")
At first glance I don't see any duplications in Event, as mentioned in exception. What should I fix in entities mapping description to resolve the problem according my scheme? Thank you!
Both Event and Auditorium map to column named id.
Specify a different column name in Auditorium or use #AttributeOverride in Event to override the default name.
When you map an entity with annotations, you do not need to repeat yourself on hibernate.cfg.xml. Try to delete it e run your code again.
Updating my answer based on Dragan Bozanovic's, Auditorium should NOT have an #Id annotated field (but we can't see that from your code, if it has).

How to use a foreign key within a composite primary key?

I'd like to create a composite primary key with hibernate. Usually I'd go for #IdClass.
But this time I want to use a foreign key also inside the composite primary key.
Question: is that possible at all?
Example:
#Entity
class Person {
long id;
}
class CarPK implements Serializable {
private int code;
private String name;
public CarPK(int code, String name) {
this.code = code;
this.name = name;
}
}
#Entity
#IdClass(CarPK.class)
class Car {
#Id
private int code;
#Id
private String name;
//can I also mark "person.id" with #Id?
#ManyToOne
#JoinColumn(name = "fk_person_id", foreignKey = #ForeignKey(name = "fk_person"))
private Person person; //assume car is shared
}
The person reference will show in database as fk_person_id. Is it possible to also add this column to the primary key of the car table?
So I'd be getting similar to: CONSTRAINT car_pkey PRIMARY KEY (code, name, fk_person_id)?
Update:
#ManyToOne
#JoinColumn(name = "id")
private Person person;
Results in: Property of #IdClass not found in entity path.to$Car: id
Yes, you can add the #Id to the join column, but you must use the key type in your IdClass. I'm doing exactly the same thing in my current project.
#Entity
#IdClass(MyIdClass.class)
public class MyObject {
#Id
private String key;
#Column
#Lob
private String value;
#ManyToOne(cascade = CascadeType.PERSIST)
#Id
#JoinColumn(name = "id")
private MyOtherObject otherObject;
...
and
public class MyIdClass implements Serializable {
private long otherObject;
private String key;
...
MyOtherObject.id is a long in this scenario.

Mapping JPA entity with composite key

I am trying to map an entity with a composite key, but I need the composite key to be the id of other entity and a String, this is my class at the moment but I believe there may be something wrong.
#Entity
public class Permission implements Serializable {
#Id
#Column
private String permission;
#Id
#ManyToOne(optional = false)
#JoinColumn(name = "role_id", foreignKey = #ForeignKey(name = "fk_permission_role_id"))
private Role role;
.....
Assuming the ID in role is a simple Integer, you might use something like:
public class PermissionPK implements Serializable {
private String permission;
private Integer role;
}
And then add the #IdClass annotation to your entity:
#IdClass(PermissionPK.class)
#Entity
public class Permission implements Serializable {
#Id
private String permission;
#Id
#ManyToOne(optional = false)
#JoinColumn(name = "role_id")
private Role role;
}
This will allow you to uses EmployeePK instances in find operations, but it isn't needed for anything else.

#OneToOne Hibernate with annotations. Can't properly save

I can't make my foreign keys auto generate using hibernate and jpa with annotations. Everything seems ok, The entries are saved in database. All the date come from one form which, when submited creates an User object with ModelAttribute and then saves it in Database.
Here are my beans. Anything else i should add ?
#Entity
#Table(name="adress")
public class Adress implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="adress_id")
private Integer adressId;
#NotBlank(message="The city must be completed")
#Column(name="city")
#Size(min=5,max=30)
private String city;
#NotBlank(message="The street must be completed")
#Column(name="street")
#Size(min=5,max=30)
private String street;
#NotNull(message="The street number must be completed")
#NumberFormat
#Column(name="street_no")
private Integer streetNo;
#OneToOne
#JoinColumn(name="user_id")
private User user;}
and the other one:
#Entity
#Table(name="users")
public class User implements Serializable {
#Id
#Column(name="user_id")
#GeneratedValue(strategy=GenerationType.AUTO)
private Integer userId;
#NotBlank(message="Username can't be blank")
#Size(min=5,max=30)
#Column(name="username")
private String username;
#NotBlank(message="Password field can't be blank")
#Size(min=5,max=30)
#Column(name="password")
private String password;
#NumberFormat
#NotNull(message="Age field must not be blank")
#Column(name="age")
private Integer age;
#Column(name="message")
#Size(min=0,max=100)
private String message;
#Column(name="date")
#DateTimeFormat(pattern="dd/mm/yyyy")
private Date dateCreated;
#OneToOne(mappedBy="user",cascade=CascadeType.ALL,fetch=FetchType.EAGER)
private Adress adress;
+getters and setters for them
public void save(T entity){
sessionFactory.getCurrentSession().save(entity);
}
If I understand you correctly and you're trying to get Hibernate to set the foreign key on your related record this might help. Try getting rid of mappedBy and instead specify the JoinColumn. This works for me on a one to many:
The order:
#Entity
#Table(name = "`order`")
public class Order implements Serializable {
#Id
#GeneratedValue
private Long id;
// Order columns...
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "order_id")
private Set<Item> items;
}
The item:
#Entity
#Table(name = "item")
public class Item implements Serializable {
#Id
#GeneratedValue
private Long id;
// Item columns...
#ManyToOne(optional = false)
#JoinColumn(name = "order_id", referencedColumnName = "id", nullable = false)
private Order order;
}
in adress class
#OneToOne(mappedBy="adress")
private User user;
and in user class
#OneToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER,optional=false)
#PrimaryKeyJoinColumn
private Adress adress;

Categories