Unidirectionnel relationship : Remove cascade - java

I have two tables :
CREATE TABLE IF NOT EXISTS `DB`.`global_history` (
`ID` INT(11) AUTO_INCREMENT,
`ID_HISTORY` INT(11) NULL,
PRIMARY KEY (`ID`),
CONSTRAINT `FK_HISTORY_GLOBAL_HISTORY`
FOREIGN KEY (`ID_HISTORY`)
REFERENCES `DB`.`history` (`ID`)
ON DELETE NO ACTION
ON UPDATE NO ACTION);
Second table :
CREATE TABLE IF NOT EXISTS `DB`.`history` (
`ID` INT(11) AUTO_INCREMENT,
`TIMESTAMP` DATETIME NOT NULL,
PRIMARY KEY (`ID`));
but when I try to delete a row in History (Second table) I get this error :
--> Cannot delete or update a parent row : a foreign key constraint fails
And I want the relationship to be #ManyToOne So when I remove a row from global_history it will not remove any row from history
And this is my model class :
Global history :
#ManyToOne
#JoinColumn(name = "ID_HISTORY", nullable = true)
private History history;
--> history is a simple class

when you define a F.K from a child (global_history) to parent (History table), child table can not has invalid F.K. so you should decide for deleting parent which cause F.K will be invalid.
a foreign key with cascade delete means that if a record in the parent table is deleted, then the corresponding records in the child table will automatically be deleted. This is called a cascade delete in SQL Server.
so if you want to prevent deleting corresponding child rows , you can set null value or default value by using following command:
ON DELETE SET NULL
ON DELETE SET DEFAULT
this is complete format:
CREATE TABLE child_table
(
column1 datatype [ NULL | NOT NULL ],
column2 datatype [ NULL | NOT NULL ],
...
CONSTRAINT fk_name
FOREIGN KEY (child_col1, child_col2, ... child_col_n)
REFERENCES parent_table (parent_col1, parent_col2, ... parent_col_n)
ON DELETE CASCADE
[ ON UPDATE { NO ACTION | CASCADE | SET NULL | SET DEFAULT } ]
)
https://www.techonthenet.com/sql_server/foreign_keys/foreign_delete.php

Related

Hibernate Criteria Join latest status and filter result

I have a table of Orders, and a table of Order Status Updates that points to order.id. I need to get a list of Orders, but I need to join in order status updates because I don't want orders which last status is 'Cancelled'
CREATE TABLE `orders` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`end_customer_id` bigint(20) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `FK_end_customer` (`end_customer_id`),
CONSTRAINT `orders_ibfk_3` FOREIGN KEY (`end_customer_id`) REFERENCES `end_customers` (`id`) ON UPDATE CASCADE,
) ENGINE=InnoDB AUTO_INCREMENT=100333 DEFAULT CHARSET=utf8;
CREATE TABLE `order_status_updates` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`status` varchar(255) NOT NULL,
`date` datetime NOT NULL,
`order_id` bigint(20) NOT NULL,
PRIMARY KEY (`id`),
KEY `FK_order` (`order_id`),
CONSTRAINT `order_status_updates_ibfk_3` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
) ENGINE=InnoDB AUTO_INCREMENT=344180 DEFAULT CHARSET=utf8;
Current Criteria is:
final Criteria c = criteria("o")
.add(eq("o.endCustomer.id", endCustomerId));
return list(c.addOrder(desc("createdAt")));
I need to filter out Orders which latest status (sorted by Date) is Cancelled
Assuming a class called MyOrder and an ORDER_STATUS enum as well as id, status and createdAt field definitions:
final Criteria c = sessionFactory.getCurrentSession().createCriteria(MyOrder.class);
c.add(Restrictions.eq("id", yourId))
.add(Restrictions.ne("status", ORDER_STATUS.CANCELLED)
.addOrder(Order.desc("createdAt"));

Hibernate: How to define map values column name?

I have a class with map inside. It is mapped with use of join table.
#Entity
#Table(name = "Sources")
#Lazy(false)
public class Sources {
#ManyToMany( fetch = FetchType.EAGER )
#JoinTable( name = "sources_lists", joinColumns = #JoinColumn( name = "list_id" ) )
#MapKeyColumn( name = "source_id" )
public Map<Integer, Source> getSources() { return sources; }
public void setSources( Map<Integer, Source> sourcesList ) { this.adSources = adSourcesList; }
private Map<Integer, Source> sources;
#Override
#Id #GeneratedValue(strategy = GenerationType.AUTO)
#Column( name="id", unique = true, nullable = false, updatable = false )
public Integer getId() { return super.getId(); }
}
I receive the following exception: "Unknown column 'sources0_.sources' in 'field list'".
When I change 'list_id' column name to the 'sources' things work, but I can't do this in production.
Tables are:
CREATE TABLE `sources` (
`id` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`) );
CREATE TABLE `source` (
`DTYPE` varchar(31) NOT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
`className` varchar(255) DEFAULT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`));
CREATE TABLE `sources_lists` (
list_id` int(11) NOT NULL,
`source_id` int(11) NOT NULL,
KEY `FK54DCBD0B4307D0FC` (`source_id`),
KEY `FK54DCBD0B575FBECF` (`list_id`),
CONSTRAINT `FK54DCBD0B4307D0FC` FOREIGN KEY (`source_id`) REFERENCES `source` (`id`),
CONSTRAINT `FK54DCBD0B575FBECF` FOREIGN KEY (`list_id`) REFERENCES `sources` (`id`));
I realized that the issue was not with column, but with somethings else: I want to map Source objects by its id and Hibernate assumes that there are 3 columns in join table: parent object id (Sources class, list_id column), object id (Source class, source_id column) and a separate column for map key. I'll open other question to ask what is the way to map object in Hibernate by its id.

MySQL. When trying to delete few duplicate rows, it deletes the last and does not delete any further

I've got tables Artist, Concert, and Artist_Concert, which contains many-to many connections between Artist and Concert.
The problem is: after adding a Concert with few Artists, when trying to delete rows from Artist_Concert, it only deletes only one row and nothing happens when trying to delete any others.
This is how I'm trying to delete rows in Java:
stat = connect.createStatement();
res = stat.executeQuery ("SELECT idConcert FROM concerthall.concert where ConcertName = '"+conc+"';");
res.first();
int idconc = res.getInt(1);
stat.execute ("DELETE FROM concerthall.artist_concert WHERE idConc="+idconc+"");
Artist
CREATE TABLE IF NOT EXISTS `concerthall`.`Artist` (
`idArtist` INT NOT NULL AUTO_INCREMENT,
`ArtName` VARCHAR(45) NOT NULL,
`ArtFee` INT NULL,
PRIMARY KEY (`idArtist`))
ENGINE = InnoDB
Artist-Concert
CREATE TABLE IF NOT EXISTS `concerthall`.`Artist_Concert` (
`idCA` INT NOT NULL AUTO_INCREMENT,
`idArt` INT NOT NULL,
`IdConc` INT NOT NULL,
INDEX `idart_idx` (`idArt` ASC),
INDEX `idconc_idx` (`IdConc` ASC),
PRIMARY KEY (`idCA`),
CONSTRAINT `idart2`
FOREIGN KEY (`idArt`)
REFERENCES `concerthall`.`Artist` (`idArtist`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `idconct4`
FOREIGN KEY (`IdConc`)
REFERENCES `concerthall`.`Concert` (`idConcert`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
Concert
CREATE TABLE IF NOT EXISTS `concerthall`.`Concert` (
`idConcert` INT NOT NULL AUTO_INCREMENT,
`ConcertName` VARCHAR(45) NOT NULL,
`ConcertDateTime` DATETIME NOT NULL,
`Organizator` INT NOT NULL,
PRIMARY KEY (`idConcert`),
INDEX `concertorg_idx` (`Organizator` ASC),
CONSTRAINT `concertorg`
FOREIGN KEY (`Organizator`)
REFERENCES `concerthall`.`Organizator` (`idOrganizator`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
The easiest way to drop duplicates is:
ALTER IGNORE TABLE table ADD UNIQUE INDEX( a, b );
In the INDEX() part, enter the name(s) of the column(s) you only want unique entries for. I think you want:
ALTER IGNORE TABLE concerthall.artist_concert ADD UNIQUE INDEX( idConc );
Then drop the index.

JPAControllers from entities not working for parent-child create

I have a parent and child table.
schema: parent(int id,varchar desc), child(int id, varchar desc, int parent_id(foreignKey)).
From this I created entities and then JPAControllers from those entities using netbeans.
When I tried to store a parent with a collection of child it throws java.lang.IllegalArgumentException: An instance of a null PK has been incorrectly provided for this find operation.. After inspecting the JPA controllers generated by netbeans, I found out that they are assuming that the child objects in the parent have an ID and in my case since the child objects are also new I don't have an ID for them. But what I don't understand is that why the following code is present in the netbeans generated JPAController code.
Collection<Child> attachedChildCollection = new ArrayList<Child>();
for (Child childCollectionChildToAttach : parent.getChildCollection()) {
childCollectionChildToAttach = em.getReference(childCollectionChildToAttach.getClass(), childCollectionChildToAttach.getId());
attachedChildCollection.add(childCollectionChildToAttach);
}
parent.setChildCollection(attachedChildCollection);
Does anybody know any way to solve this other than manually editing JPAControllers.
Below code snippet shows how I tried to store parent.
Parent parentObj = new Parent();
parentObj.setDesc("parent");
Collection<Child> childCollection = new ArrayList<>();
Child childObj = new Child();
childObj.setDesc("child1");
childCollection.add(childObj);
Child childObj2 = new Child();
childCollection.add("childObj2");
parentObj.setChildCollection(childCollection);
parentJpaController.create(parentObj);
script for creating tables given below
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='TRADITIONAL';
CREATE SCHEMA IF NOT EXISTS `mydb` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci ;
USE `mydb` ;
-- -----------------------------------------------------
-- Table `mydb`.`PARENT`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`PARENT` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`DESC` VARCHAR(45) NULL ,
PRIMARY KEY (`ID`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `mydb`.`CHILD`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `mydb`.`CHILD` (
`ID` INT NOT NULL AUTO_INCREMENT ,
`DESC` VARCHAR(45) NULL ,
`PARENT` INT NOT NULL ,
PRIMARY KEY (`ID`) ,
INDEX `FK_CHILD_PARENT` (`PARENT` ASC) ,
CONSTRAINT `FK_CHILD_PARENT`
FOREIGN KEY (`PARENT` )
REFERENCES `mydb`.`PARENT` (`ID` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;

JDBC mysql meta.getExportedKeys() returning empty resultset

Hi I'm trying to get the foreig key for a given table, I'm using this code :
ResultSet rs = meta.getImportedKeys(_con.getCatalog(), null, _tableName);
while (rs.next())
{
//get the foreignKeys
}
ResultSet rs2 = meta.getExportedKeys(_con.getCatalog(), null, _tableName);
while (rs2.next())
{
//get the foreignKeys
}
The resultSet is empty, although the table contains a foreign key and is a foreign key to another table,
the getImportedKeys works fine.
Thanks for any suggestions.
Tables :
CREATE TABLE `COMMANDE` (
`COMMANDE_ID` int(11) NOT NULL,
`CLIENT_ID` int(100) DEFAULT NULL,
`TOURNEE_ID` int(100) DEFAULT NULL,
PRIMARY KEY (`COMMANDE_ID`),
KEY `CLIENT_ID` (`CLIENT_ID`),
KEY `TOURNEE_ID` (`TOURNEE_ID`),
CONSTRAINT `commande_ibfk_1` FOREIGN KEY (`CLIENT_ID`) REFERENCES `CLIENT` (`CLIENT_ID`),
CONSTRAINT `commande_ibfk_2` FOREIGN KEY (`TOURNEE_ID`) REFERENCES `TOURNEE` (`TOURNEE_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `CLIENT` (
`CLIENT_ID` int(100) NOT NULL,
`LIBELLE` varchar(100) DEFAULT NULL,
PRIMARY KEY (`CLIENT_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
I tried the code with both tables.
I think the problem is from the rather curious naming of the methods in JDBC, and the hard to grok description.
To get primary keys of a table, you should use getPrimaryKeys(), to get the foreign key of a table (and the primary key they reference), use getImportedKeys()
There are additional methods
- getExportedKeys() exposes the foreign keys that reference the specified table (so the table parameter specifies the table with the primary key)
- getCrossReference() is a combination of all of the above: you need to specify the tables on both sides of the constraint

Categories