I have a problem with mapping many-to-one relationship without exact foreign key constraint set in database. I use OpenJPA implementation with MySql database, but the problem is with generated sql scripts for insert and select statements.
I have LegalEntity table which contains RootId column (among others). I also have Address table which has LegalEntityId column which is not nullable, and which should contain values referencing LegalEntity's "RootId" column, but without any database constraint (foreign key) set.
Address entity is mapped:
#Entity
#Table(name="address")
public class Address implements Serializable {
...
#ManyToOne(fetch=FetchType.LAZY, optional=false)
#JoinColumn(referencedColumnName="RootId", name="LegalEntityId", nullable=false, insertable=true, updatable=true, table="LegalEntity")
public LegalEntity getLegalEntity() {
return this.legalEntity;
}
}
SELECT statement (when fetching LegalEntity's addresses) and INSERT statment are generated:
SELECT t0.Id, .., t0.LEGALENTITY_ID FROM address t0 WHERE t0.LEGALENTITY_ID = ? ORDER BY t0.Id DESC [params=(int) 2]
INSERT INTO address (..., LEGALENTITY_ID) VALUES (..., ?) [params=..., (int) 2]
If I omit table attribute from mentioned statements are generated:
SELECT t0.Id, ... FROM address t0 INNER JOIN legalentity t1 ON t0.LegalEntityId = t1.RootId WHERE t1.Id = ? ORDER BY t0.Id DESC [params=(int) 2]
INSERT INTO address (...) VALUES (...) [params=...]
So, LegalEntityId is not included in any of the statements.
Is it possible to have relationship based on such referencing (to column other than primary key, without foreign key in database)? Is there something else missing?
Thanks in advance.
Try changing your FetchType to eager. OpenJPA should not query for the LegalEntity until it's requested by calling getLegalEntity.
Also, the absence of constraints shouldn't matter (somebody please correct me if I'm wrong).
Related
I am a beginner when it comes to JPA and I am struggling to write the proper entity classes for my database structure.
Firstly, here are my tables:
create table article (
id varchar(100) not null primary key,
title varchar(255) not null
)
create table article_provider (
providerId varchar(60) not null,
articleId varchar(100) null,
isOnSale BOOL NOT NULL,
constraint article_provider_articleid_fk foreign key (articleId) references article (id) on update cascade on delete cascade
)
As you can see I have a one-to-many relationship (every article can have 0..n providers).
Now when accessing articles I would also like to know, if the article is on sale by any of it's providers. For this I would use the following SQL query:
SELECT article.*, MAX(article_provider.isOnSale) AS isOnSale FROM article
LEFT JOIN article_provider ON article.id = article_provider.articleId
GROUP BY article.id
How would I best go about fetching this type of result using Hibernate/JPA?
Your query is not right -- you use attributes in SELECT clause that are not in GROUP BY clause, but for example to select Article.id + MAX(whatever) you can use something like:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Article> query = builder.createQuery(Article.class);
Root<Article> root = query.from(Article.class);
Join<Article, ArticleProvider> join = root.join(Article_.provider, JoinType.LEFT);
query.multiselect(root.get(Article_.id), builder.max(sale));
query.groupBy(root.get(Article_.id));
// query will return collection of scalar attributes (ID + Number)
Object result = entityManager.createQuery(query).getResultList()
To select exactly Article.* + MAX(sales) you would need to use the above as a subquery and join again with Article entity.
But there are simillar of examples elsewhere: How do I write a MAX query with a where clause in JPA 2.0?
EDIT:
another tip: https://www.thoughts-on-java.org/hibernate-tip-subquery-criteriaquery/
correction/clarification: I have only assumed you want to use Criteria API where subquery and combining the results for Hibernate is probably the only way. But you may try to use JPA query language and/or different provider where subquery with multiple results can be used -- jpa eclipselink subquery in from clause
I have a many-to-many relationship between two entities:
Entity A
ID
NAME
Entity B
ID
NAME
Join Table A_B
A_ID
B_ID
I'm trying to do an insert based off of the secondary unique attributes (names). I want to avoid fetching each entity by their name and then saving (2 queries & 1 insert vs 1 insert). Effectively, I'm looking to do something like this:
#Query(nativeQuery = true, value = "INSERT INTO A_B(A_ID, B_ID) VALUES ((SELECT ID FROM A WHERE NAME = ?), (SELECT ID FROM B WHERE NAME = ?))")
void addToJoinTable(String nameA, String nameB);
I saw this post, but I'm getting exceptions because an insert doesn't return a result set. The post mentions setting nativeQuery to true would resolve the issue, but I've had no such luck... Is there another & better way to do this?
Disclaimer: I am new to JPA, so this might be a stupid question...
I am using Java Jdbc connection.
My question is very simple, I am inserted the employee record in a employee table
Ex:
Insert into employee (emp_id,emp_name) values(10,'hello');
How could I fetch the foreign key for child table(address) and insert it?
If I use select max(emp_id) from employee and Insert the id into child table
I'm afraid of if more than one person try to insert the values in employee table and there is a possibilities that I can get a wrong employee id for the child table.
Is there any possible way to insert the employee id in child table.
Note:I require a sql query for how to insert the employee id in child table
If you insert a record into a table that contains an AUTO_INCREMENT column, you can obtain the value stored into that column by calling the mysql_insert_id() function.
More details to refer this link
https://dev.mysql.com/doc/refman/5.0/en/getting-unique-id.html
You need to do a couple of things.
Assumed, your primary key in employee is not an AUTO_INCREMENT with the name emp_id and your inserting like Insert into employee (emp_id,emp_name) values(10,'hello'); you're done: the foreign key is 10.
BUT: if it is really an AUTO_INCREMENT, you must not specify any value for it:
Insert into employee (emp_name) values('Veronica');
You may then retrieve the last generated emp_id value by the driver or by a subsequent SQL statement. In JAVA, you need to tell the driver, that you want to have the last generated ID back:
PreparedStatement pst = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
Then you are able to fetch the generated primary key:
ResultSet rset = pst.getGeneratedKeys();
Long emp_id;
if (rset.next()) {
emp_id = rset.getLong(1);
}
Now Long emp_id contains the foreign key to insert in to address table.
I have two tables:
Table1: orders
idOrder,
Blockquote
idUser
Table2: ordersinfo
idOrder,
.......,
.......
idOrder is primary a key for two tables. I have to delete from this tables rows by idUser. I tried different ways, but nothing helped me.
My Questions: What query, I should use?
I have this exception
MySQLIntegrityConstraintViolationException
You will need to issue two delete statement
-- Delete OrderInfo table
DELETE FROM ordersinfo
WHERE EXISTS (SELECT 1
FROM orders
WHERE orders.idOrder = ordersinfo.idOrder
AND IdUser = ???)
-- Delete Orders
DELETE FROM Orders
WHERE IdUser = ???
I have two tables connected by a foreign key with a one to many relation.
In entity A I have the following:
#org.hibernate.annotations.Cascade( {
org.hibernate.annotations.CascadeType.ALL,
org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
#OneToMany(mappedBy="monitoredFlight", fetch = FetchType.LAZY)
#OnDelete(action=OnDeleteAction.CASCADE)
private List<bTable> BTable = new ArrayList<BTable>();
Now I try to delete from table A with a bulk delete query:
Query query = em.createQuery("delete from A where originDateTime<:date");
and I get the foreign key constraint error. I decided to do the delete with a join just as I would in mysql, so I changed it to:
Query query = em.createQuery("delete from A join BTable where originDateTime<:date");
and I got a syntax error. I have tried several combination with or without join and nothing works; any ideas?
I am using mysql for the database and java for the language.
You can use a native query, the following should work in mysql:
delete a , b from a inner join b on a.id=b.a_id where ...
You can setup a foreign key with the parameter on delete cascade so that when the key it references is deleted all rows that it is a foreign key on are also deleted.