I have two tables. I want to join both but there is no joint column between them. To generate joint column, i added new field on my cell entity. Field name is cityCode, which is created by lac column substring index 1 to 3 then converted to int. So actually when you check DB you cant see cityCode column. I didnt store it on DB.
I have city entity also and it has id column which is name cityCode also.
I want to join tables with cityCode columns.
Here is my json list
cell entity : https://jsoneditoronline.org/?id=a5ed0c0ab0c249f89c9360ecca3f0750
city entity : https://jsoneditoronline.org/?id=205565db82014c75b292122f141239c8
I code non-existing column by using code below. it works well as u see it on my cell entity json.
#Getter(AccessLevel.NONE)
#Setter(AccessLevel.NONE)
#Column(name = "LAC", insertable = false, updatable = false)
private Integer cityCode;
public Integer getCityCode()
{
return Integer.parseInt(lac.substring(1,3));
}
I try to use code below it throws error.
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name = "cityCode")
private City city;
oracle.jdbc.OracleDatabaseException: ORA-00904: "GCELL6900X0_"."CITY_CODE": invalid identifier
its looking CITY_CODE column on DB so i know why it throws error but i couldnt found any solution.
Related
I have one table Message in which I keep both incoming and outgoing messages. A column "category" is kept to differentiate, that can have 1 = INCOMING, 2 = OUTGOING. Outgoing messages can have attachments. The following is my Message entity class:
#Entity("MESSAGE")
class Message{
Long id; //primary key
String additionalStringId;
private Long senderId;
private Long receiverId;
Category messageCategory;
#OneToMany(
mappedBy = "message",
cascade = CascadeType.ALL,
orphanRemoval = true)
private List<AttachmentEntity> outgoingAttachments= new ArrayList<>();
}
The problem is that AttachmentEntity is linked with the message via the "additionalStringId" and I can not impact the database schema.
class AttachmentEntity{
#ManyToOne
#JoinColumn(name = "additionalStringId", referencedColumnName = "additionalStringId")
private Message message;
}
I know it's not working snipping code but my problem appears when sender = receiver, when I try to send a message to myself. In that case in my database I will have two messages, with the same additionalStringId but with category = 1 and the other with category = 2. My attachment entity list tries to link to message but two messages are visible. What can I do to fix this problem?
I tried separating the two categories into separate entities with #Where and #DiscriminatorFormula and #DiscriminatorValue but I could not get it to work. What can I do?
Table DDLs:
CREATE TABLE "MESSAGE"
( "ID" NUMBER NOT NULL ENABLE,
"MESSAGE_ID" VARCHAR2(60) NOT NULL ENABLE,
"CATEGORY" NUMBER,
"SENDER_ID" NUMBER,
"RECEIVER_ID" NUMBER )
CREATE TABLE "OUTBOX_ATTACHMENT"
( "ID" NUMBER NOT NULL ENABLE,
"MESSAGE_ID" VARCHAR2(60) NOT NULL ENABLE,
)
#ManyToOne(cascade = CascadeType.PERSIST)
#JoinColumn(name = "additionalStringId", referencedColumnName = "id", nullable = false)
private Message message;
#OneToMany(mappedBy = "message", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<AttachmentEntity> outgoingAttachments = new ArrayList<>();
something like this might work.
I think the problem you are facing is not at the JPA level, but at the table definition level (DDL).
If you change the table definition as shown below, the FK relationship becomes easy to establish:
CREATE TABLE "MESSAGE"
( "ID" NUMBER NOT NULL,
"MESSAGE_ID" VARCHAR2(60) NOT NULL,
"CATEGORY" NUMBER,
"SENDER_ID" NUMBER,
"RECEIVER_ID" NUMBER,
constraint uq1 unique (category, message_id)
);
CREATE TABLE "OUTBOX_ATTACHMENT"
( "ID" NUMBER NOT NULL ,
category number not null constraint chk1 check (category = 2),
"MESSAGE_ID" VARCHAR2(60) NOT NULL ,
constraint fk1 foreign key (category, message_id)
references message (category, message_id)
);
As you can see the FK includes two columns: category, and message_id. But, as per requirements, in the attachement table category can only accept attachment to outgoing messages (value 2).
I have two tables:
users:
user_id (primary)
ip (unique)
etc ..
services_to_ip
id (primary)
service_id
ip
etc ..
In class User:
#OneToMany()
#JoinColumn(name = "ip", insertable = false, nullable = false, updatable = false)
public List<QPlanService> getPlanServices() {
return planServices;
}
Using MySQL query log we get something like that:
SELECT *
FROM services_users planservic0_
LEFT OUTER JOIN services qservice1_
ON planservic0_.service_id = qservice1_.id
WHERE planservic0_.ip = 777
In WHERE condition the 'user_id' field used (the default field is primary key - users.id) (user_id=777).
How can I specify that I need to take the value of the 'ip' field from User entity, not 'user_id'?
I will be grateful for any help!
JoinColumn will only specify the name of the column holding the foreign key, so changing the name of joincolumn absolutely will not help.
Hibernate will be using the primary key by default for joining, if you want to override this you can simply use referencedColumnName in your relation, but the referenced column should be unique
As Amer Qarabsa mentioned above:
#OneToMany()
#JoinColumn(name = "ip", insertable = false, nullable = false, updatable = false, referencedColumnName="ipcolumnName")
public List<QPlanService> getPlanServices() {
return planServices;
}
I have a class ReleaseNote saved in the table RELEASE_NOTES and a table RELEASE_NOTE_USER_READ with the columns RELEASE_NOTE_ID and USER_ID where I want to save which users have already read a releaseNote, so I don't show it again.
Since we are using a microservice architekture I don't have a user object in that microservice and don't want to add one. Although it won't be a problem to add a field usersRead to the ReleaseNote which contains the userId of all the users who have read the releaseNote.
I need to perform two actions:
Pass a list of releaseNoteIds to be saved in the table for a given userId, so I can keep track of the releaseNotes a user has read.
Select all releaseNotes a user has not read. The SQL-Statement for this would look like:
SELECT * FROM RELEASE_NOTES WHERE ID NOT IN (SELECT RELEASE_NOTE_ID FROM RELEASE_NOTE_USER_READ WHERE USER_ID = :userId)
How can I achieve this using the EntityManager or Hibernate specific functionality?
Found the solution myself. Add field Set usersRead to ReleaseNote and annotate like the following:
#ElementCollection
#CollectionTable(name = "RELEASE_NOTES_USER_READ",
joinColumns = #JoinColumn(name = "RELEASE_NOTE_ID"))
#Column(name = "USER_ID", table = "RELEASE_NOTES_USER_READ")
private Set<Integer> usersRead = new HashSet<>();
I have a table containing customer data in an oracle database. Here is a simplified definition:
CUSTOMER (CUSTOMER_ID NUMBER NOT NULL,
SOURCE_SYSTEM VARCHAR2(30),
FULL_NAME VARCHAR2(360),
PHONE_NUMBER VARCHAR2(240)
)
The primary key for this table is (CUSTOMER_ID, SOURCE_SYSTEM).
The table has numerous rows for which SOURCE_SYSTEM is null. At the database level, there is no issue, however when I try to access any of these rows via JPA Entity, it causes a number of issues:
1: Using em.find() to fetch a row with a null SOURCE_SYSTEM always results in a null being returned.
2: Using em.merge() to upsert a row with a null SOURCE_SYSTEM succeeds if the record does not exist in the table, but fails on subsequent updates because the merge ALWAYS results in an insert being run.
3: Using em.createQuery() to explicitly query for a row with a null causes the following exception:
Exception [EclipseLink-6044] (Eclipse Persistence Services - 2.3.1.v20111018-r10243):
org.eclipse.persistence.exceptions.QueryException
Exception Description: The primary key read from the row [ArrayRecord(
CUSTOMER.CUSTOMER_ID => 1
CUSTOMER.FULL_NAME => GUY PERSON
CUSTOMER.PHONE_NUMBER => 555-555-1234
CUSTOMER.SOURCE_SYSTEM => null)] during the execution of the query was detected to be null.
Primary keys must not contain null.
Query: ReadAllQuery(referenceClass=Customer sql="SELECT CUSTOMER_ID, FULL_NAME, PHONE_NUMBER, SOURCE_SYSTEM FROM CUSTOMER WHERE ((CUSTOMER_ID = ?) AND (SOURCE_SYSTEM IS NULL))")
Unfortunately, "Primary keys must not contain null" seems pretty final. I was unable to find too much information on workarounds for this error, which makes it seem like there is no solution.
THE QUESTION: I would like to know if anyone has any Java code-based solution that don't involve making changes to the database. My current workaround is to use ROW_ID as the #Id of the table, but this means I can no longer use em.merge() or em.find().
Here are my Java classes:
Customer.java:
#Entity
#Table(name = "CUSTOMER")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
#EmbeddedId
private Customer_Id key;
#Column(name = "CUSTOMER_ID", nullable = false, insertable = false, updatable = false)
private Long customerId;
#Column(name = "SOURCE_SYSTEM", length = 30, insertable = false, updatable = false)
private String sourceSystem;
#Column(name = "FULL_NAME", length = 360)
private String fullName;
#Column(name = "PHONE_NUMBER", length = 240)
private String phoneNumber;
//Setters, Getters, etc
...
}
Customer_Id.java
#Embeddable
public class Customer_Id implements Serializable {
private static final long serialVersionUID = 1L;
#Column(name = "CUSTOMER_ID", nullable = false)
private Long customerId;
#Column(name = "SOURCE_SYSTEM", length = 30)
private String sourceSystem;
//Setters, Getters, etc
...
}
Primary keys cannot contain null (in JPA or in databases). Use a different value such as "" or " ".
Is the customer_id unique? if so then just remove the sourceSystem from the Id.
Otherwise, you could try logging a bug to have support for null ids added.
I have three tables , a main table MAIN_TB with foreign keys to table TCHARS and TSTATUSES, when i persist MAIN_TB, re-query and display the saved record, the joined columns(tchars from TCHARS and t_status from TSTATUSES) are null but data is saved. what could i be missing?
Table MAIN_TB
#JoinColumn(name = "T_STATUS", referencedColumnName = "T_STATUS")
#ManyToOne
private Tstatuses tStatus;
#JoinColumn(name = "T_CHAR", referencedColumnName = "T_CHAR")
#ManyToOne
private Tchars tChar;
Table TCHARS
#OneToMany(mappedBy = "tChar")
private Collection<MainTb> mainTbCollection;
Table TSTATUSES
#OneToMany(mappedBy = "tStatus")
private Collection<MainTb> mainTbCollection;
Code
public void saveMainTb(){
MainTb mainTb = new MainTb();
Tchars tchars = new Tchars();
Tstatuses tstatuses = new Tstatuses();
tchars.setTChar(new Short("1"));
mainTb.setTChar(tchars);
tstatuses.setTStatus(new Short("1"));
mainTb.setTStatus(tstatuses);
mainTb.setTName("test");
em.persist(mainTb);
}
Result
![Result][1]
Any help would be appreciated
since there is no cascading specified on either owning side or inverse side. I reckon you can try the following code to manually save all entity instances:
em.persist(tchars);
em.persist(tstatuses);
mainTb.setTChar(tchars);
mainTb.setTStatus(tstatuses);
em.persist(mainTb);
You can add the below code to your tStatus and tChar.
fetch=FetchType.EAGER
This will hit the performance, if you don't need to fetch the 2 above objects, always.
Instead, you can add the fetch clause in your query, to fetch the two child objects(tStatus and tChar), along with your mainTb object. This will save you the trouble and fetch all the child objects, you've specified in your fetch clause. Performance optimizer.