#OneToMany does not create the join table - java

I'm new to JPA. Suppose I have these two entities:
//Imports
#Entity
#Table(name="article", schema = "sch_client")
public class Article implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int price;
private int amount;
//Getters & setters
}
And
#Entity
#Table(name="purchase", schema = "sch_client")
public class Purchase implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
#OneToMany
private List<Article> listArticle;}
I want to have something like a purchase contains many articles.
My question is: is it possible with only #OneToMany in Purchase class that points to Article class to have the desired relationship (a purchase contains many articles). Or to use a #OneToMany annotation I have to add a #ManyToOne on Article class. If so, why is is mandatory to add the #ManyToOne? any explanation please.
Thanks in advance.

First of all, I have write a misleading title, I will change it to make it more accurate:
Old title : In JPA, is it possible to use #OneToMany without using #ManyToOne?
New title : #OneToMany does not create the join table.
As I said, I'm new to JPA, my problem can appear dumb, I could delete the question, but I decided to keep it in case someone someday will face similar situation, it can help!
The join table of Purchase and Article was created every time I executed the code very normally, but I didn't notice!, I was checking the logs of NetBeans
and didn't see the join table, I was misled by those logs, I think that a join table doesn't appear in the logs (I hope that someone can confirm this information and make an edit of this answer).
I have created Purchase and Article in a new schema named: sch_sales. and the join table was created in public schema (PostgreSQL).
So, to make it more correct I added schema to #JoinTable as shown below, like this I will have all my tables in the same schema.
#Entity
#Table(name="purchase", schema = "sch_sales")
public class Purchase implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
#OneToMany
#JoinTable(name="join_purchase_article", schema = "sch_sales", joinColumns = #JoinColumn(name="sales_fk"), inverseJoinColumns = #JoinColumn(name="article_fk"))
private List<Article> listArticle;
}
UPDATE :
I was having a 3rd table created containing the id of Purchase and Article (a join table) which is obviously not correct.
The normal "behavior" is to have an id_purchase column added in Article, in this page I have find how to have such a result.
To have the desired result, I used the code below:
#Entity
#Table(name="purchase", schema = "sch_sales")
public class Purchase implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
#OneToMany
#JoinColumn(name="id_purchase")
private List<Article> listArticle;
}

Related

Design review: Spring JPA entity versioning with "version switching"

I'm writing backend for a cms of sorts that needs to support having different versions of its entities and also the ability to choose which of the versions is the current/active one. I've looked around on this site and others and found some advice on implementing versioning (which I've taken to heart) but nothing in terms of "version switching", as I call it.
My question is twofold, I suppose:
1) I want to know if there is any (preferably open-sourced) system that does something similar? Are there any design patterns that are related to what I'm doing?
2) I would appreciate a review of my implementation below.
Here's a rundown of my entities:
Firm:
#Entity
public class Firm {
#Id #GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#OneToOne
#JoinTable(name = "firm_firm_version")
private FirmVersion firm;
FirmVersion:
#Entity
public class FirmVersion {
#EmbeddedId private FirmVersionId id;
private String name;
#ManyToMany(mappedBy = "firmVersion")
private List<Staff> staff = new ArrayList<>();
FirmVersionId:
#Embeddable
public class FirmVersionId implements Serializable {
private Long id;
private Integer version;
}
FirmStaff:
#Entity
public class FirmStaff {
#Id #GeneratedValue
private Long id;
#ManyToMany
private List<FirmVersion> firmVersion = new ArrayList<>();
private String name;
// ...fields
}
This works fine, but my main concern is the propagation of these #ManyToMany relations. The way I implemented it, every time you update a staff you create 1) a new staff and 2) a new FirmVersion and however many table rows it takes to link them, which I imagine can get out of hand pretty quickly.

String as Entity ID inserted by user [EclipseLink]

[INTRO]
Database : Apache Derby
JPA : EclipseLink
Hey, I was looking for answer but couldn't find any so here it goes. I'm writing simple sudoku app, and the next feature which I would like to add is saving my Sudoku boards in database, and retrieve them when it's needed. Here is UML diagram of my main two classes:
SudokuBoard.uml
The structure of my two entities are as follows :
The SudokuBoard entity:
#Entity
public class SudokuBoard implements Serializable, Cloneable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private static final long serialVersionUID = 1L;
#OneToMany(cascade=CascadeType.PERSIST)
private ArrayList<SudokuField> board;
public ArrayList<SudokuField> board() {
return board;
}
public void setBoard(ArrayList<SudokuField> board) {
this.board= board;
}
public Long etId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
The SudokuField entity:
#Entity
public class SudokuField implements Serializable, Comparable<SudokuField>,
Cloneable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Transient
private static final Logger logger =
LoggerFactory.getLogger(SudokuField.class);
#Transient
private static final long serialVersionUID = 1L;
#Basic(fetch = FetchType.EAGER)
#Column(name = "Value")
private int value;
#ManyToOne
#JoinColumn(name = "board_fk", referencedColumnName = "id")
private SudokuBoard sudokuBoard;
The execution in DAO:
#Override
public void write(SudokuBoard obj, String path) throws
FileNotFoundException, IOException {
entityManager.getTransaction().begin();
entityManager.persist(obj);
entityManager.getTransaction().commit();
}
[PROBLEM]
I wonder if there is any possiblity to not use auto generated key but instead use String as PK in SudokuBoard entity. In my application I implemented binding so I would like to save the same object of SudokuBoard which is changing over time under different names.
Hope I stated my intentions clearly. Thanks for any help and tips how it could be done.
Using String as primary key is straightforward - just declare it as such and drop the #GeneratedValue annotation.
However, changing the primary key (if that's what you mean by 'saving the same object (...) under different names') is not possible. If you try to persist/merge an existing entity under a different primary key, JPA will either raise an exception or treat it as a new entity, resulting in duplicate entries in the database. Simply put, assigning id to an entity is permanent.
All in all, I'd suggest you keep an autogenerated surrogate key and declare another unique String field for the name. Conveying business information using technical fields is rarely a good idea.

hibernate, stackoverflow with particular entity mapping

I have the following mapping:
#Entity
public class Satellite implements Serializable, Comparable<Satellite> {
#NotNull #Id
private long id;
.....
#OrderColumn
#OneToMany(mappedBy = "satellite", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<DataModel> dataModel;
}
and a child entity:
#Entity #IdClass(value=DataModelPK.class)
public class DataModel implements Serializable, Comparable<DataModel> {
private static final long serialVersionUID = -3416403014857250990L;
#Id
private int orbit; // related to reference orbit file
private int dataPerOrbit; // in Gbit
#ManyToOne #Id
private Satellite satellite;
}
originally, DataModel was an embeddable entity, but for a better control over the primary key and the underlying structure of the db, I switched to a more traditional model.
The point is, during the loading of the entity now it generate a stack overflow!! I think there is some cyclic loading between those two entities and it got stuck!
I'm thinking to revert everything back to what it was, but I wish to understand why it gives me this error.
You have #IdClass for DataModel specified to be DataModelPK.class but your #Id annotation is on an int field.
This is a problem, it may be causing you stackoverflow but I am not certain.
Update I now see the second #Id annotation so I stand corrected, I will investigate furtuer.

Spring Rest servcie prodouces JSON but not for objects mapped with a db

It took me hours to realize, what the problem is:
I have a Spring Rest service and a GET-Method which returns a user in JSON-Format.
The data comes from my database over sessionFactory.
After debugging it turned out, that the Problem is related to my bidrectional onetomany-manytoone relationship.
So calling
User user = (User) sessionFactory.getCurrentSession().load(User.class, userId);
returns a User-Object where user.getCity().getSupplier() runs into an com.sun.jdi.InvocationException. Therefore Jackson is obviously unable to serialize.
But what causes this exception?
#Entity
#Table(name = "T_CITY")
public class City implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private long id;
#OneToMany(mappedBy = "city", cascade=CascadeType.ALL)
private Set<User> user;
#OneToMany(mappedBy = "city", cascade=CascadeType.ALL)
private Set<Supplier> supplier;
User:
#Entity
#Table(name = "T_USER")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
public User() {
}
#Id
private long id;
#ManyToOne
private City city;
Supplier:
#Entity
#Table(name = "T_SUPPLIER")
public class Supplier implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private long id;
#ManyToOne
private City city;
As mentioned in the other answer, I think you'll find that your issues are related to the x-to-x relationships. This can sometimes create circular reference issues when trying to jsonify the entity beans.
Sometimes you can avoid or get past this by using annotations, other times a wrapper class is needed. I often just write a wrapper class to handle my JSON transactionts
There are many many references to this type of issues spanning many languages. Here a few starting points for you to research.
Google related search regarding circular references in entity objects
Json and Java - Circular Reference
Circular Dependencies With Jackson

ManyToMany table with extra column Hibernate

I'm having an auto generated table by hibernate for the relationship between a User and Chat (a chat can have multiple users and a user can have multiple chats):
==User Model==
#Entity
public class User implements Serializable{
#Id
#GeneratedValue
private int userId;
private String username
==Chat Model==
#Entity
public class Chat implements Serializable{
#Id
#GeneratedValue
private int chatId;
private String subject;
#ManyToMany
private List<User> users;
#ManyToOne
private User created;
This generates a new table called Chat_User with the ID's of the user and the chat. Now I need another field (lastSeen) to be added in this generated table. How can this be realized? For now I have a new model that look's like the one below, but it is not working:
#Entity #Table(name = "Chat_User", catalog = "pdl") public class ChatUser implements Serializable {
#Id
#ManyToOne
#JoinColumn(name="users_userId", nullable=false)
private User user;
#Id
#ManyToOne
#JoinColumn(name="Chat_chatId", nullable=false)
private Chat chat;
#Temporal(javax.persistence.TemporalType.TIMESTAMP)
private Date lastSeen;
It will throw an exception: Unknown column 'lastSeen' in 'field list'. When I manually create this in the database it works somehow, but then it creates multiple entries (one with the lastSeen as value NULL and one with the correct value). Please help.
You would need to create an Embedable Class and use the Association override to override the join table. Click here for a link to sample code by mkyong . Let me know if you need any more help.

Categories

Resources