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.
Related
I designed a database model like this. In this, I'd like to store user info from Facebook when they use Facebook or Google to login.
I use JPA with Hibernate to work with Database, so I need to map the database model to ORM.
What I tried:
I tried MappedSuperclass for SnsProfile abstract class but It doesn't work when I need to map SnsProfile with User entity.
I tried #Inheritance(strategy = InheritanceType.SINGLE_TABLE) but if I have some more Social Sites and additional properties, the table is more and more complicated.
I would like to have some JPA Entity like this:
public class User implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String password;
private String email;
private UserStatus status;
#OneToMany(fetch = FetchType.LAZY,
cascade = CascadeType.ALL,
mappedBy = "user")
private List<SnsProfile> profile;
}
public abstract class SnsProfile implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String snsId;
#ManyToOne(fetch = FetchType.LAZY, optional = false)
#JoinColumn(name = "user_id", nullable = false)
private User user;
}
public abstract class FacebokProfile extends SnsProfile {
// Properties here
}
public abstract class GoogleProfile extends SnsProfile {
// Properties here
}
Could you please give me some advice on Entity design to the database model above work well on JPA? Or any changes in Database model are welcome.
Please help. Thank you so much!
Is it possible to have multiple #EmbeddedId composite keys defined for a #ManyToOne relationship between classes? Example:
Entity 1
#Entity
#AttributeOverrides({ #AttributeOverride(name="pk.method", column=#Column(name = "http_method", nullable = false)) })
#AssociationOverrides({ #AssociationOverride(name = "pk.operation", joinColumns = #JoinColumn(name = "id_operation", nullable = false)) })
public class Action {
#EmbeddedId
private ActionId pk = new ActionId();
}
#Embeddable
private class ActionId implements Serializable {
#ManyToOne private Operation operation;
private HttpMethod method;
}
Entity 2:
#Entity
#AssociationOverrides
// Need to override the embedded if attributes of the Action entity inside the UserActionId class
public class UserAction {
#EmbeddedId private UserActionId pk = new UserActionId();
}
#Embeddable
private class UserActionId implements Serializable {
// How to provide a #JoinColumn for the Action.pk composite key (action.pk.authURL) and #Column for (action.pk.httpMethod)
#ManyToOne private Action action;
#ManyToOne private User user;
}
Is this possible? I have tried but keep getting a Hibernate error saying that the FK must have the same number of columns as the ActionId pk.
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;
I have the following two classes, one ReqCandAssociation can have many Comments and it is mapped like so. I need to figure out a way that when I delete a ReqCandAssociation it deletes all of its associated comments. Thanks
#Entity
#Table(name = "candidate_jobReq")
public class ReqCandAssociation implements Serializable {
#Id
private Integer candidateId;
#Id
private Integer jobId;
#Column(name = "reqStatus")
private String reqStatus;
#ManyToOne
#PrimaryKeyJoinColumn(name="candidateId", referencedColumnName="id")
private Candidate candidate;
#ManyToOne
#PrimaryKeyJoinColumn(name="jobId", referencedColumnName="id")
private JobReq jobReq;
public ReqCandAssociation(){
}
Second class
#Entity
#Table(name="comment")
public class Comment {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
#Column(name="commentText")
private String commentText;
#Column(name="commentDate")
private Date commentDate;
#ManyToOne
#PrimaryKeyJoinColumn(name="reqCandAssociationId", referencedColumnName="id")
private ReqCandAssociation reqCandAssociation;
#ManyToOne
#PrimaryKeyJoinColumn(name="userId", referencedColumnName="id")
private User user;
Change this to the following, i'm making it bidirectional mapping.
#Entity
#Table(name = "candidate_jobReq")
public class ReqCandAssociation implements Serializable {
#Id
private Integer candidateId;
#Id
private Integer jobId;
#Column(name = "reqStatus")
private String reqStatus;
#OneToMany(cascade = { CascadeType.ALL }) //this is added here.
#JoinColumn(name ="reqCandAssociationId")
private Set<Comment> comments;
-----
Readup more on the cascade options. All cascade types are all|none|save-update|delete|all-delete-orphan|delete-orphan
The cascade all will delete all the comments associated to this class.
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.