HIbernate creates table without foreign key - java

I'm trying to create OneToOne unidirectional relationship with shared Primary Key. According to this tutorial all I need is a #PrimaryKeyJoinColumn annotation on parent side:
#Entity
#Table(name="cities")
public class City {
#Id
#GeneratedValue
#Column(name = "city_id")
private int id;
#Column
private String name;
#OneToOne(cascade = CascadeType.ALL)
#PrimaryKeyJoinColumn
private Mayor mayor;
}
#Entity
#Table(name="mayors")
public class Mayor {
#Id
#Column
private int id;
#Column
private String firstName;
#Column
private String secondName;
}
Hibernate successfully build tables, but mayors table has no foreign key.
What I'm doing wrong?

Related

Spring Data JPA XRef With PK Object Mapping

I'm having a hard time getting Spring Data to persist the values into an XREF Table. I'm attempting to talk to an existing DB so i cannot change the schema which would have made this easier.
Classes
#Entity
#Table(name="user_type")
class UserType {
#Id
#Column(name="name")
private String name;
}
#Entity
#Table(name="user_role")
class UserRole {
#Id
#Column(name="name")
private String name;
}
#Entity
#Table(name="company")
class Company{
#Id
#Column(name="id")
private UUID id;
#Column(name="name")
private String name;
}
#Entity
#Table(name="user")
class User {
#Id
#Column(name="id")
private UUID id;
#Column(name="email")
private String email;
#ManyToOne
#JoinTable
private UserType userType;
//not sure what to do here or which JoinTable/ManyToOne/Etc
private UserCompanyAccess userCompanyAccess;
}
#Entity
#Table(name="user_company_access")
class UserCompanyAccess {
#EmbeddedId
private UserCompanyAccessId userCompanyAccessId;
// not sure of relationships here either
private User user;
private Company company;
private UserRole userRole;
#Embeddable
static class UserAccessCompanyId implements Serializable {
#Column(name="id")
private UUID id;
}
}
I have tried many different combinations of #JoinColumns specifying the user(id) and userAccessCompany(user_id) as well with company. The code compiles but at runtime hibernate either throws an error saying company_id not provided or other random exceptions regarding trying to compare uuid to character varying etc which was really weird. Any help would be appreciated. I have done many #OneToMany/#ManyToOne/#ManyToMany but somehow never through spring data with an XREF table where the PK is not a composite of the 2 joining tables. That's what is throwing me off. Otherwise the #EmbeddedId would be the combination of the two.
The dark brown section of the spreadsheet is confusing, because it suggests there's a CompanyUser table that you haven't mentioned elsewhere. Is that an issue?
Regardless, it's a shame you can't adjust the schema, because this design has a lot of flaws. However, it should still be possible to use it. I'm a little stale on Java and Spring/Boot, and I don't have a useful way to test them easily, but you may have better luck with these:
#Entity
#Table(name="user")
class User {
#Id
#Column(name="id")
private UUID id;
#Column(name="email")
private String email;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_type", table="user_type", referencedColumnName = "name")
private UserType userType;
}
#Entity
#Table(name="user_type")
class UserType {
#Id
#Column(name="name")
private String name;
}
#Entity
#Table(name="user_role")
class UserRole {
#Id
#Column(name="name")
private String name;
}
#Entity
#Table(name="company")
class Company{
#Id
#Column(name="id")
private UUID id;
#Column(name="name")
private String name;
}
#Entity
#Table(name="user_company_access", uniqueConstraints = {
#UniqueConstraint(columnNames = { "user_id", "company_id" })
})
class UserCompanyAccess {
#Id
#Column(name="id")
private UUID id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "role", table="user_role", referencedColumnName = "name")
private UserRole userRole;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "user_id", table="user", referencedColumnName = "id")
private User user;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = "company_id", table="company", referencedColumnName = "id")
private Company company;
}
Explanation: The user_company_access table is where everything ultimately gets tied together. It's designed such that any particular combination of user and company to be unique, and #UniqueConstraint enables that in the code; you don't really need an embeddable object for that.

Jpa, linked class take main class id

I have a Product :
#Data
#Entity
#Table(name = "products", schema = "laboratory", catalog = "laboratory")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Product {
#Id
#GeneratedValue
private int id;
#ManyToOne(fetch = FetchType.LAZY, cascade= CascadeType.ALL)
#JoinColumn(name = "project_id")
#Transient
private Project project; // this one is for read only
#Column(name="project_id") // this will save the id in db for the project
private int projectId;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="id")
private Inspection inspection;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="id")
private Information information;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="id")
private Departure departure;
private String un;
private String tc;
}
There is 3 class that this product needs in order to be a Product : Information, Inpection, Departure
All 3 of these classes are similar.
I want to link them by the Product.id witch is a #GeneratedValue AI in sql.
Here is one of the 3 class :
Information
#Data
#Entity
#Table(name = "products_informations", schema = "laboratory", catalog = "laboratory")
#JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class Information {
#Id
private int productId;
private String description;
private String model;
private int year;
private String serialNumber;
private int odometre;
private int noCrochet;
private int nbKeys;
private String localisation;
private String cemeteryPosition;
#JsonFormat(pattern = "yyyy-MM-dd")
private Date receptionDate;
}
I want, WHEN I save() the product, that the private String productId in this class to automatically take the Id from the Product class without having to do it manually in my controller.
You have the mappings backwards in your model.
By using
public class Product {
#Id
#GeneratedValue
private int id;
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="id")
private Information information;
You've told JPA to use the PRODUCT.ID primary key as a foreign key to the Information table; foreign keys are controlled by the relationship, so it means your ID value is pulled from the information.productId value. Opposite of what you are asking for and it means you have 4 mappings trying to set the PRODUCT.ID column value (set them different and see for yourself).
Try this instead:
public class Product {
#Id
#GeneratedValue
private int id;
#OneToOne(mappedby="product", cascade = CascadeType.ALL)
private Information information;
..
}
public class Information {
#Id
private int productId;
#MapsId
private Product product;
..
}
With this you will need to set the Information.product reference, but JPA will use that to set your productId value, using the one you set within the product.id property. You just need to set this relationship when you add an Information instance to a product. Do the same for the other relationships

How to set Id of one entity to the Id of another entity using JPA?

I'm new at Spring Boot's JPA concept so need your help in deciding how to import just the ID of another entity, say User into HealthData entity. Following is my User entity:
#Entity
#Table(name = "user",uniqueConstraints = {#UniqueConstraint(columnNames = "email")})
public class User {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column(nullable = false)
private String name;
#Email
#Column(nullable = false)
private String email;
private String imageUrl;
#Column(nullable = false)
private Boolean emailVerified=false;
#JsonIgnore
private String password;
#NonNull
#Enumerated(EnumType.STRING)
private AuthProvider authProvider;
private String providerId;
}
And I wish to define HealthData entity in the following manner :
#Entity
#Table(name = "HealthData",uniqueConstraints = {#UniqueConstraint(columnNames = "id")})
public class HealthData {
#Id
private Long id; //how to import id of User here?
#Column
private Double height;
#Column
private Double weight;
#Column
private int age;
...other columns
}
Now, I wish to use Id of User to this entity(kind of making parent-child relationship) . I don't want to add User class object in HealthData. I thought of using #OneToOne in HealthData but then it would add User in it. How can i just include Id from parent table in child table?
In this case, your HealthData has a reference to User, and I'm not sure why you wouldn't have mapped this as a foreign key. If you are able to do so, I'd suggest the following:
#Entity
#Table(name = "HealthData")
public class HealthData {
#Id
#OneToOne
#JoinColumn(name = "id")
private User user;
#Column
private Double height;
#Column
private Double weight;
#Column
private int age;
...other columns
}
JPA then handled setting the "ID" to the value within your user instance for you, and can persist both in the same transaction automatically. Allowing references to be marked as IDs is known as a derived ID and supported I believe since JPA 2.0.
As for efficiency, you can still lazy fetch or even not fetch the user instance. It is simple to just map the ID column as a basic using a slightly different approach:
#Entity
#Table(name = "HealthData")
public class HealthData {
#Id
private Long id;
#MapsId
#OneToOne(optional = false, fetch = FetchType.LAZY)
#JoinColumn(name = "id")
private User user;
#Column
private Double height;
#Column
private Double weight;
#Column
private int age;
...other columns
}
JPA will set both the User id as well as the healthData.id values based on what it generates for the user Id sequence when you set the healthData.user reference.
You can use getters and setters to set the value of user id in the healthdata table.

Understanding onetomany and manytoone JPA

I can't understand how works oneToMany and manyToOne in JPA. For a sample I have to entity.
#Entity
public class Customer {
#Id
#GeneratedValue
private long id;
private String name;
private List<Skills> skillList
}
and another one
#Entity
public class SkillList {
private String skillName;
private byte skillLevel;
}
How to correct link this entities? Also If anyone can explain it in an accessible way.
In database one to many relationship is achieved by foreign key.
In order to link two entities in Java according to JPA specification you should use #ManyToOne annotation or both #ManyToOne and #OneToMany if you need bidirectional association.
#Entity
public class Customer {
#Id
#GeneratedValue
private Long id;
private String name;
#OneToMany(mappedBy = "customer")
private List<Skill> skills;
}
#Entity
public class Skill {
#Id
#GeneratedValue
private Long id;
private String skillName;
private byte skillLevel;
#ManyToOne
private Customer customer;
}
It will generate two tables in the database. Table SKILL has column CUSTOMER_ID which relates to CUSTOMER table.

How to convert this UML to JPA entities

I have this UML diagram.
And I tried to build entities like this (I renamed Entity class to Entidad)
RelationshipType.java
#Entity
#Table(name = "relationship_type")
public class RelationshipType {
#Id
#GeneratedValue
private Long id;
private String type;
#OneToMany(mappedBy = "relationshipType", fetch = FetchType.EAGER)
private Set<Relationship> relationships = new HashSet<Relationship>();
//Getters and Setters
Relationship.java
#Entity
#Table(name = "relationship")
public class Relationship {
#Id
#ManyToOne
private RelationshipType relationshipType;
#Id
#ManyToOne
private Entidad entity;
//Getters and Setters
Entidad.java
#Entity
#Table(name = "entity")
public class Entidad {
#Id
#GeneratedValue
private Long id;
private String image;
private String foundationNotes;
private String alias;
private Boolean excludeNotifications;
private String notes;
//[...]
#ManyToOne
private Relationship related;
#OneToMany(mappedBy = "entity", fetch = FetchType.EAGER)
private Set<Relationship> relationships = new HashSet<Relationship>();
But when I launch app throws this:
Foreign key (FK_9d8afoh1pv9r59iwjkbcpnud1:entity [])) must have same number of columns as the referenced primary key (relationship [relationshipType_id,entity_id])
At now, I don't know where is the problem and need do this well because I'm using this entities to build the DB schema.

Categories

Resources