I've the following relationship:
class Product { // 10000s many of them
#ManyToMany
List<Category> categories; //usually 0-5
}
and
class Category {
...with no back link...
}
now if I delete a category and then I load a product that has that category I will get an error that contains:
update or delete on table "categories" violates foreign key constraint (...) is still referenced from table product_category
I've seen a number of answers and tutorials, but the problem is that many do propose to add Product as a bidirectional relationship in Category, then before removing a category I will go through all Products and remove that particular category. But products are thousands here and the operation will be too long.
This could be so simple by using normal SQL, but I'd like to keep the automatic loading of of categories and the mapping of the properties. Is there a lightweight way to automatically do this without keeping a list of products in each category?
What you're trying to do does not make lot of sense IMO.
You want to keep unidirectional relation but want a way to delete the other side directly.
But I understood that the problem was the huge dataset (category -> product).
One way to solve this would be to mix in the same transaction a JPQL(to delete the category) and a native query (to delete rows from the join-table).
em.createNativeQuery("delete from product_category where category_id = ?").setParameter(1, category.getId()).executeUpdate();
em.remove(category);
Related
I have a JPA many to many relation.
The easiest way of deleting all entries of this relation is doing a findAll(), clearing the collection of the assoziation and flushing the session.
In my case this means loading ~1'000'000 instances into ram just to delete them all. That's not really efficient.
I could resort to SQL and simply truncate the join table. Is there an efficient way to do this in JPA?
You would need to map your m-m table as an additional entity and delete it with a delete statement. If the table is not mapped to an entity, it cannot be deleted by a delete statement. If you just want to delete the m-m relations, this should be enough. If you also wnat to delete related entities, you should map them to the new m-m entity and mark the relationship with cascade on delete.
I have a DatabaseObject in Java which can dynamically retrieve information from a database and store it in key-value pairs (it is just an extended LinkedHashMap).
My DatabaseObject can load, delete, update, and insert values into a table, based on provided columns that match the database table.
I have a "Company" table and a "Category" table in my database, and each company can have multiple categories. I also have a "CompanyCategories" table where each company's category is recorded. These are what the tables look like:
Company
CompanyID, Name
Category
CategoryID, Name
CompanyCategories
CompanyCategoryID, CompanyID, CategoryID
In SQL, I normally will apply a simple join with group concatentation to get a row that looks like this:
CompanyID, Name, Categories
1, Dummy Company, Photographer;Videographer
I am trying to figure out how to best pull this information into a Company object in Java that contains references to another Category object. In my view, I'm not pulling the CategoryID or the CompanyCategoryID, but I will need those if I delete a category from a company, since it's in a separate table.
My question is would it be better to execute several SQL statements back to back? In other words:
SELECT * FROM company WHERE CompanyID=1; SELECT * FROM category WHERE CompanyID=1;
And then in Java combine them into a Company object with a List of Category objects, or should I let the database do the joining and just include a lot of extra information in my view?
SELECT * from company_view
CompanyID, Name, CompanyCategoryIDs, CategoryIDs, Categories
1, Dummy Company, 4;6, 2;3, Photographer;Videographer
My problem with the later is that it's going to quickly become problematic to keep straight, while I'm worried about performance with the former. For a single company, it's not going to be a big deal, but 2000-4000 companies could be loaded at any one time.
I really like the object oriented approach I'm taking to dealing with my database tables, but I'm not sure how best to deal with views.
Which would be more efficient?
I'm developing a Java desktop application (SE, JDK 1.6.0) connecting directly to a remote MySQL Server (5.0) via EclipseLink 2.3.0, using a Swing GUI.
The application where my problem occurs looks like this: the user issues a search for companies (e.g. all companies located in X) and the results are loaded in a JTable. When a user selects a company much additional data from other related tables is shown (e.g. notes about the company, employees, phone number of employees etc.), most of them are #OneToMany relations.
Because of the amount of data and tables needed for each entry I have to optimize my search query to use joins and batch fetch:
import org.eclipse.persistence.config.QueryHints;
import javax.persistence.Query;
Query query = entityManager.createQuery("SELECT DISTINCT c FROM Company c WHERE c.y = x");
query.setHint(QueryHints.LEFT_FETCH, "c.companyWebsiteCollection");
query.setHint(​QueryHints.BATCH, "c.person2companyRelationCollection");
List list = query.getResultList();
The problems occur with person2companyRelationCollection which holds relations to persons who have relations to other companies which have connections to other persons and companies etc.
When I select company1 in jTable1 and all related persons are shown in table2, an INSERT query is issued that tries to insert the shown person2CompanyRelation entity again into the DB, causing a om.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry.
What am I doing wrong with my query hints?
Additional information:
I don't detach any objects
I don't merge any objects
all entities are managed by the same EntityManager
all is done within the same transaction
the PK of Person2companyRelation is a composite primary key (#EmbeddedId) containing
companyId
personId
relationTypeId
the problem doesn't occur when only using with query.setHint(​QueryHints.LEFT_FETCH)
Correction: the problem does occur when batch-fetching any object using QueryHints.BATCH, regardless of the key type
Are you detaching objects, mixing objects from different queries/transaction/entity managers, are you using merge?
Does the insert occur without using batch fetch?
How is the Id of the object and the relationship mapped?
I have two models, say :
BlogPost(title, message)
Tags(name)
Both have a ManyToMany relationship defined.
Using JPQL, I delete a list of BlogPost with this query:
DELETE FROM BlogPost b WHERE b IN :list
(:list is a List from a previous SELECT requet).
Doing so, I have a ConstraintViolationException because of the relation between BlogPost and Tags.
Is there a way to delete the relation without deleting the Tags using JPQL?
Thanks for your help!
You have to remove the association first, before you delete the entity.
JPA create a table BlogPost_Tags which stores ID of BlogPost and Tags.
So when you try to delete a BlogPost, the constraint on the BlogPost_Tags failed.
You need to delete the relation before delete the Post, and there is no easy way in JPQL, you have to use the EntityManager.
I'll answer myself with the solution I came up. I'm not sure it's the best one, but at least, it works.
Since you want to bulk delete something that have a ManyToMany related items, you first have to delete the relation (in the join table), or do a loop and for each item, delete manually (insane and too much heavy).
So, since JPQL does not allow to do it, a possible way is to make a native SQL query for deleting the id you want in the related table, and then, do the bulk delete.
Let's say I have two tables, employee and department where emp has a #ManyToOne key to dept. Now I want to be able to delete rows from the dept table but keep the emp records pointing to it; basically saving the relationship so that when the dept table is recreated the relationship is restored. (This actually happens in our system, but not with hibernate, but by using composed, reproducable keys).
The question is: Will hibernate crash on #ManyToOne relationships which seem to be there but with no record in the #One part of the relationship? (basically an inconsistent database state).
I probably should solve this by removing the #ManyToOne relationship and simply map the foreign key to a String or so. I just wondered whether we can pull it off to leave the relationship in place..
Now I want to be able to delete rows from the dept table but keep the emp records pointing to it;
Then you'll have to delete them logically, not physically (and FK constraints will actually prevent you from deleting departments).
Will hibernate crash on #ManyToOne relationships which seem to be there but with no record in the #One part of the relationship?
Don't you have referential integrity (see above)? But let's say you broke the integrity... Maybe you'll be able to load employees but something is going to crash at some point (when loading the association, if not before).
I probably should solve this by removing the #ManyToOne relationship and simply map the foreign key to a String or so. I just wondered whether we can pull it off to leave the relationship in place..
Delete the departments logically.