Hi I want to create an Entity which doesn't have an ID.
#Entity
#Table(name="USER_PROD_LIC_TYPE_ALL")
public class UserProdLicTypeAll {
#EmbeddedId
private UserProdLicTypeAllPK id;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="USER_ID")
private User user;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="LICENSE_TYPE_ID")
private LicenseType licType;
....
}
since it doesn't have primary key i created Embeddable class as below:
#Embeddable
public class UserProdLicTypeAllPK {
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="USER_ID")
private User user;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="LICENSE_TYPE_ID")
private LicenseType licType;
...
}
The combination of these two fields returns a unique value.
But it doesn't work. I get
org.springframework.beans.factory.UnsatisfiedDependencyException: exception.
Do i need to have references in User and LicenseType entities for both UserProdLicTypeAll and UserProdLicTypeAllPK? I have tried that also but still it doesn't work.
This is my private hell. I'm not sure what the best way to solve it properly.
My best solution is:
#Entity
#Table(name = TableName.AREA_USER)
#IdClass(UserAreaPK.class)
public class UserArea implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = UserAreaPK.C_AREA_ID)
private Long areaId;
#Id
#Column(name = UserAreaPK.C_USER_ID)
private String userId;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name = UserAreaPK.C_AREA_ID, insertable = false, updatable = false)
private Area area;
And
/**
* Primary key for the relationship User-Area
*/
public class UserAreaPK implements Serializable {
protected static final String C_AREA_ID = "area_id";
protected static final String C_USER_ID = "user_id";
private static final long serialVersionUID = 1L;
#Id
#Column(name = C_AREA_ID)
private Long areaId;
#Id
#Column(name = C_USER_ID)
private String userId;
Related
i am tryning to join two entities where typDossAmo can have a list of DossMedic
but i get the following error:
Entity class [class ma.cnss.wstest.TypDossAmo] must use a #JoinColumn instead of #Column to map its relationship attribute [drugs].
public class TypDossAmo implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "ID")
private BigInteger id;
#Id
#Basic(optional = false)
#NotNull
#Size(min = 1, max = 9)
#Column(name = "NUM_DOSS")
private String numDoss;
#Column(name = "p_tab_medic")
#OneToMany(mappedBy="doss")
private List<DossMedic> drugs;........
public class DossMedic implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
protected DossMedicPK dossMedicPK;
#Column(name = "ID")
private BigInteger id;
#Column(name = "NOMBRE")
private BigInteger nombre;
#ManyToOne(fetch=FetchType.LAZY)
#JoinColumn(name="NUM_DOSS")
private TypDossAmo doss;
The idea of the annotation #Column is for common columns without any relationship with other tables, when you use #JoinColumn is to say to the ORM that two tables have a relationship and the way to join them is with this column.
In this case the solution is change the annotation #Column by #JoinColumn in TypDossAmo
public class TypDossAmo {
#JoinColumn(name = "p_tab_medic")
#OneToMany(mappedBy="doss")
private List<DossMedic> drugs;
}
In my application I have 3 core classes as described below.
public class Semana {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Integer series;
private String observacao;
private Integer ordenacao;
#OneToMany(mappedBy = "semana")
#JsonBackReference
#OrderBy("ordenacao asc ")
private List<TreinoOrdenado> treinoOrdenados;
}
public class TreinoOrdenado {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "id_semana")
private Semana semana;
#ManyToOne
#JoinColumn(name = "id_treino")
private Treino treino; // can be repeated in the database but with different "ordenacao"
private Integer ordenacao;
}
#Table(name = "exercicio_ordenado")
public class ExercicioOrdenado {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#ManyToOne
#JoinColumn(name = "id_treino")
#JsonBackReference
#ToString.Exclude
private Treino treino;
#ManyToOne
#JoinColumn(name = "id_exercicio")
private Exercicio exercicio;
private Integer ordenacao;
#ManyToOne
#JoinTable(name = "parametro")
private Parametro parametro;
}
And this Parametro class which is a relationship between those 3 classes.
public class Parametro {
#EmbeddedId
private ParametroId parametroId = new ParametroId();
#MapsId("semana")
#OneToOne
#JoinColumn(name = "semana_id")
private Semana semana;
#MapsId("treino")
#OneToOne
#JoinColumn(name = "treino_id")
private TreinoOrdenado treino;
#MapsId("exercicio")
#OneToOne
#JoinColumn(name = "exercicio_id")
private ExercicioOrdenado exercicio;
private Integer series;
private String repeticoes;
private String observacao;
}
public class ParametroId implements Serializable {
#Column(name = "semana_id")
private Long semana;
#Column(name = "treino_id")
private Long treino;
#Column(name = "exercicio_id")
private Long exercicio;
}
So, here is my problem. I want to be able to access the Parametro from it's parent class ExercicioOrdenado, but in order to be distinguishable in the database the class Parametro needs the reference from the other two (Semana, TreinoOrdenado).
With my current mapping I got this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource
[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.MappingException: Foreign key (FK73ewcy2r50kw71o4he51dkolv:parametro
[parametro_exercicio_id,parametro_semana_id,parametro_treino_id])) must have same number of columns as the referenced primary key (parametro [id])
I can persist paremetros in the database with:
parametros.setSemana(semana);
parametros.setExercicio(exercicioOrdenado);
parametros.setTreino(treinoOrdenado);
parametroRepository.save(parametros);
But I can't retrieve from ExercicioOrdenado with the mapping.
I don't know the right approach to do this.
I think i now a way...
To do this we can use #Embeddable and #EmbeddedId annotation.
In this link have exemples.
https://www.baeldung.com/jpa-composite-primary-keys
#Entity
public class Parametro {
#EmbeddedId
private ParametroId parametroId;
#OneToOne
#JoinColumn(name = "exercicio_id")
#ForeignKey(name = "fk_exercicio_id")
private ExercicioOrdenado exercicio;
#OneToOne
#JoinColumn(name = "semana_id")
#ForeignKey(name = "fk_semana_id")
private Semana semana;
#OneToOne
#JoinColumn(name = "treino_id")
#ForeignKey(name = "fk_treino_id")
private TreinoOrdenado treino;
private Integer series;
private String repeticoes;
private String observacao;
}
#Embeddable
public class ParametroId {
private log id;
private log semana;
private log treino;
private log exercicio;
}
I believe that this is the way to create a personalized primary key using jpa. I have not tested the relationships of entities in the primary key. I know that there is more than one form to do that.
JPA #OneToOne with Shared ID -- Can I do this Better?
I have got 3 entity. These are: Tweet,Thread and Media. I am using Hibernate JPA Annotations. When i save one Thread object, it must trigger to tweet and automatically tweet must saved like thread and Tweet's "media" must saved of course.
You can see my entity class as below. Right now i'm working on Tweet beetween Thread. When i use these code, The number of thread is being recorded as much as tweet object. But i want that only one record inside thread.
Process must be like that after saved thread:
add a new record to Thread table. (only one row)
add all tweet to tweet table(all of "threadid" column same because these tweets belong only one thread!)
add all media to media table(all of "tweetid" column same )
Tweet Table:
#Entity
#Table(name = "tbl_tweet")
public class Tweet implements Serializable {
#Id
#GeneratedValue
private long id;
#Column(name = "tweetid")
private String tweetID;
private String parentTweetID;
private String avatar;
private String owner_name;
private String owner_nick;
private String content;
private String sent_time;
private String sent_date;
private String retweet_count;
private String like_count;
private String owner_link;
#ManyToOne(cascade = CascadeType.ALL)
#JoinColumn(name="threadid")
private Thread thread;
#OneToMany(mappedBy = "tweet",fetch = FetchType.LAZY,cascade = {CascadeType.PERSIST,CascadeType.MERGE})
private List<Media> mediaURLs;
Thread Table:
#Entity
#Table(name = "tbl_thread")
public class Thread implements Serializable {
#Id
#GeneratedValue
private Long id;
#Column(name = "threadid")
private String threadID;
#Transient
private List<Tweet> listOfTweets;
Media Table:
#Entity
#Table(name = "tbl_media")
public class Media implements Serializable {
#Id
#GeneratedValue
private long id;
private String mediaID;
private String mediaType;
private String mediaUrl;
private String mediaUrlHttps;
private String mediaVideoUrl;
#ManyToOne
#JoinColumn(name = "tweetid")
private Tweet tweet;
My expected and actual results:
http://prntscr.com/mkaul5
I changed that way. Right now it's working good. Long live annotations!
Tweet Table:
#Entity
#Table(name = "tbl_tweet")
public class Tweet implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(unique = true,nullable = false,name = "tweetID")
private String tweetID;
private String parentTweetID;
private String avatar;
private long owner_id;
private String owner_name;
private String owner_nick;
private String content;
private String sent_time;
private String sent_date;
private String retweet_count;
private String like_count;
#Transient
private String quotedTweetHtml;
#Transient
#JoinColumn(name = "threadid",referencedColumnName = "id")
private Thread thread;
#OneToMany(cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)
#JoinColumn(name = "tweetID")
private List<Media> mediaURLs;
Thread Table:
#Entity
#Table(name = "tbl_thread")
public class Thread implements Serializable {
#Id
#GeneratedValue
private Long id;
#Column(name = "threadid")
private String threadID;
#OneToMany(cascade = CascadeType.PERSIST,fetch = FetchType.EAGER)
#JoinColumn(name = "threadid")
private List<Tweet> listOfTweets;
Media Table:
#Entity
#Table(name = "tbl_media")
public class Media implements Serializable {
#Id
#GeneratedValue
private long id;
private String mediaID;
private String mediaType;
private String mediaUrl;
private String mediaUrlHttps;
private String mediaVideoUrl;
#Transient
#JoinColumn(name = "tweetID")
private Tweet tweet;
I have 2 entity classes - Order and OrderDetail. Below are code snippets of these two classes.
#Entity
#Table(name="orders")
#IdClass(OrderPK.class)
public class Order implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Id
private String customerEmail;
#Column(name="advance_order_time")
private Date advanceOrderTime;
#Column(name="amount")
private float amount;
#OneToMany(mappedBy = "order", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private Set<OrderDetail> orderDetailList;
public void addOrderDetail(OrderDetail orderDetail) {
if (orderDetail != null) {
if (orderDetailList == null) {`enter code here`
orderDetailList = new HashSet<OrderDetail>();
}
orderDetailList.add(orderDetail);
orderDetail.setOrder(this);
}
}
}
#Entity
#Table(name="order_details")
public class OrderDetail implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#Column(name="item_code")
private String itemCode;
#ManyToOne
#MapsId("id")
private Order order;
}
public class OrderPK implements Serializable {
//default serial version id, required for serializable classes.
private static final long serialVersionUID = 1L;
private int id;
#Column(name="customer_email")
private String customerEmail;
}
Order object and the collection of OrderDetail objects are inserted successfully in the database but the order_id column of OrderDetail in null. Below is the code snippet.
entityManager.persist(kfcOrder);
order table has a composite key id and customer_email. This id is foreign key of table order_details of column order_id.
Please suggest a work around so that while persisting order object in database order_id of order_details table also gets saved.
try this..
#ManyToOne(optional = false)
#JoinColumns({
#JoinColumn(name = "ORDER_ID",referencedColumnName = "id"),
#JoinColumn(name = "EMAIL",referencedColumnName = "customerEmail")
})
#MapsId("id")
private Order order;
optional = false will ensure that no child can exist if parent doesn't exist.
I'm having two entities Car and CarDescription where CarDescription is depending on another foreign key from the table Language.
What I' trying to accomplish is to have a HashMap in Car such that whenever I'm having a Car entity-object I am able to access all descriptions from the language id.
Entity Car.java
#Entity
#Table(name = "Car")
public class Car extends AbstractTimestampEntity implements Serializable {
private static final long serialVersionUID = -5041816842632017838L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#OneToMany(mappedBy="car")
#MapKeyColumn(name = "language_ID")
// #MapKey(name = "language") // does not work either
private Map<Long, CarDescription> carDescription = new HashMap<>(0);
}
Entity CarDescription.java
#Entity
#Table( name="car_description",
uniqueConstraints = {
#UniqueConstraint(columnNames={"language_id", "name"})
}
)
public class CarDescription extends AbstractTimestampEntity implements Serializable {
private static final long serialVersionUID = 2840651722666001938L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name = "ID", unique = true, nullable = false)
private Long id;
#NotNull
#ManyToOne
private Car car;
#NotNull
#OneToOne
private Language language;
// ..
}
Entity Language.java
#Entity
public class Language implements Serializable {
private static final long serialVersionUID = 3968717758435500381L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ID")
private Long id;
// ..
}
The problem I am having is that the mapping gives me a map from each CarDescription.id to CarDescription.
How can I accomplish a correct mapping?
In CarDescription you need to add the languageId property:
#Column(name = "language_id", insertable = false, updatable = false)
private Long languageId;
#NotNull
#OneToOne
#JoinColumn(name = "language_id")
private Language language;
public void setLanguage(Language language) {
this.languageId = language.getId();
this.language = language;
}
Then you can use it in the Car entity like this:
#OneToMany(mappedBy="car")
#MapKey(name = "languageId")
private Map<Long, CarDescription> carDescription = new HashMap<>(0);