[HY000][1215] Cannot add foreign key constraint - java

application_user
-- auto-generated definition
create table application_user
(
id bigint auto_increment
primary key,
email varchar(255) not null,
is_active bit null,
name varchar(255) not null,
password varchar(255) not null,
surname varchar(255) not null,
username varchar(255) not null
)
engine = MyISAM;
I have a table that generated by hibernate.
I want to create a table and add a foreign key manually.
So far I tried this
application_user_log
CREATE TABLE application_user_log (
log_id BIGINT NOT NULL AUTO_INCREMENT,
fk_user_id BIGINT NOT NULL,
old_user_name BIGINT NOT NULL,
new_user_name BIGINT NOT NULL,
PRIMARY KEY (log_id),
FOREIGN KEY (fk_user_id) REFERENCES application_user(id)
) ;
And I got this error message.: [HY000][1215] Cannot add foreign key constraint
Why I got this error?

Well I don't know why my answer got converted into a comment, but I knonw that MyISAM doesn't support foreign keys. You can read details here.

Related

why did not generate enableSelectByPrimaryKey when using mybatis generator

When I am using this command to generate mybatis xml file:
java -jar mybatis-generator-core-1.3.4.jar -configfile generatorConfig.xml -overwrite
everything works fine but finnaly i found the user mapper result file did not genreate SelectByPrimaryKey function. this is part of my generate file config:
<table tableName="users"
enableCountByExample="true"
enableUpdateByExample="true"
enableDeleteByExample="true"
enableSelectByExample="true"
enableSelectByPrimaryKey="true"
enableUpdateByPrimaryKey="true"
selectByPrimaryKeyQueryId="true"
selectByExampleQueryId="true">
<generatedKey column="ID" sqlStatement="JDBC" identity="true" />
</table>
my database is PostgreSQL 13. what should I do to fix it? This is my user table DML:
CREATE TABLE public.users (
id int8 NOT NULL GENERATED ALWAYS AS IDENTITY,
nickname varchar NULL,
avatar_url varchar NULL,
phone varchar NOT NULL,
updated_time int8 NOT NULL,
created_time int8 NOT NULL,
salt varchar NULL,
pwd varchar NULL,
sex int4 NULL,
level_type varchar NULL,
phone_region varchar NULL,
country_code int4 NULL,
user_status int4 NULL DEFAULT 1,
last_login_time int8 NULL,
first_login_time int8 NULL,
app_id int4 NOT NULL,
register_time int8 NULL,
apple_iap_product_id varchar NULL,
CONSTRAINT unique_phone UNIQUE (phone)
);
The DML you posted shows that the table doesn't have a primary key. You have two options.
You could define a primary key in the table by adding this to the create table statement:
create table public.users (
...
primary key (id)
);
Or, if you don't want to define a primary key in the database, you can use the "VirtualPrimaryKeyPlugin" in MyBatis Generator. See here for details: https://mybatis.org/generator/reference/plugins.html

How to execute a long MySQL script in Java without adding external libs?

I'm using JDBC MySqlDataSource class to handle a database for my app. I'm trying to make a method that formats the database for app's use - creates tables and constraints. Basically it's a script generated from phpMyAdmin export option. I've made a class called DatabaseTemplate with a static String containing the script and then I use it in my formatDatabase method.
public void formatDatabase() {
try {
sql.executeUpdate(DatabaseTemplate.GetScript());
} catch (SQLException e) {
System.out.println("Connection not found.");
e.printStackTrace();
}
}
It makes an SQL exception "Syntax not correct". My script string looks like this:
CREATE TABLE `arenas` (
`arena_id` int(11) NOT NULL,
`name` varchar(50) COLLATE utf16_polish_ci NOT NULL,
`location` varchar(50) COLLATE utf16_polish_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_polish_ci;
CREATE TABLE `contestants` (
`contestant_id` int(11) NOT NULL,
`name` varchar(50) COLLATE utf16_polish_ci NOT NULL,
`surname` varchar(50) COLLATE utf16_polish_ci NOT NULL,
`nickname` varchar(50) COLLATE utf16_polish_ci NOT NULL,
`score` int(11) NOT NULL,
`language` varchar(50) COLLATE utf16_polish_ci NOT NULL,
`contact_info` text COLLATE utf16_polish_ci NOT NULL,
`additional_info` text COLLATE utf16_polish_ci,
`team_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_polish_ci;
CREATE TABLE `matches` (
`match_id` int(11) NOT NULL,
`sideA` int(11) NOT NULL,
`sideB` int(11) NOT NULL,
`sideA_score` int(11) DEFAULT NULL,
`sideB_score` int(11) DEFAULT NULL,
`time` datetime NOT NULL,
`tournament` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_polish_ci;
CREATE TABLE `system_users` (
`sys_usr_id` int(11) NOT NULL,
`login` varchar(20) COLLATE utf16_polish_ci NOT NULL,
`pw_hash` int(32) NOT NULL,
`permissions` varchar(5) COLLATE utf16_polish_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_polish_ci;
CREATE TABLE `teams` (
`team_id` int(11) NOT NULL,
`name` varchar(50) COLLATE utf16_polish_ci NOT NULL,
`where_from` varchar(50) COLLATE utf16_polish_ci NOT NULL,
`leader_id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_polish_ci;
CREATE TABLE `tournaments` (
`tournament_id` int(11) NOT NULL,
`name` varchar(50) COLLATE utf16_polish_ci NOT NULL,
`type` enum('solo','team') COLLATE utf16_polish_ci NOT NULL,
`arena_id` int(11) NOT NULL,
`operator` int(11) NOT NULL,
`additional_info` text COLLATE utf16_polish_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf16 COLLATE=utf16_polish_ci;
ALTER TABLE `arenas`
ADD PRIMARY KEY (`arena_id`);
ALTER TABLE `contestants`
ADD PRIMARY KEY (`contestant_id`),
ADD KEY `team_id` (`team_id`);
ALTER TABLE `matches`
ADD PRIMARY KEY (`match_id`),
ADD KEY `sideA` (`sideA`),
ADD KEY `sideB` (`sideB`),
ADD KEY `tournament` (`tournament`);
ALTER TABLE `system_users`
ADD PRIMARY KEY (`sys_usr_id`);
ALTER TABLE `teams`
ADD PRIMARY KEY (`team_id`),
ADD KEY `leader_id` (`leader_id`);
ALTER TABLE `tournaments`
ADD PRIMARY KEY (`tournament_id`),
ADD KEY `arena_id` (`arena_id`),
ADD KEY `operator` (`operator`);
ALTER TABLE `contestants`
MODIFY `contestant_id` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `contestants`
ADD CONSTRAINT `contestants_ibfk_1` FOREIGN KEY (`team_id`) REFERENCES `teams` (`team_id`);
ALTER TABLE `matches`
ADD CONSTRAINT `matches_ibfk_1` FOREIGN KEY (`sideA`) REFERENCES `teams` (`team_id`),
ADD CONSTRAINT `matches_ibfk_2` FOREIGN KEY (`sideB`) REFERENCES `teams` (`team_id`),
ADD CONSTRAINT `matches_ibfk_3` FOREIGN KEY (`tournament`) REFERENCES `tournaments` (`tournament_id`);
ALTER TABLE `teams`
ADD CONSTRAINT `teams_ibfk_1` FOREIGN KEY (`leader_id`) REFERENCES `contestants` (`contestant_id`);
ALTER TABLE `tournaments`
ADD CONSTRAINT `tournaments_ibfk_1` FOREIGN KEY (`arena_id`) REFERENCES `arenas` (`arena_id`),
ADD CONSTRAINT `tournaments_ibfk_2` FOREIGN KEY (`operator`) REFERENCES `system_users` (`sys_usr_id`);
I'm guessing it's because of how String in java uses \n. I tried removing it, changing it to \r\n, it's still the same exception. How do I format this script so that it executes properly?
It might be good to read the Java documentation on issuing SQL queries as it seems you are using the wrong method in your code.
If you are curious about the difference between DDL (Data Definition Language) and DML (Data Manipulation Language), there are valuable articles on them on Wikipedia.
You might find it easier to place the sql in a dedicated file setup.sql and then load the file when needed and execute the sql from the file. If your code contains more than one SQL statement, you could store each in a separate file.
That way your SQL query will:
actually be readable to a human and
there will be no issues with multi-line strings in Java.

Hibernate + mySQL + Code Generator

I'm using Hibernate Code Generator plugin in Eclipse
When I'm export MySql structure to .java files with annotations but in files no mapping annotations
Why?
SQL
CREATE TABLE IF NOT EXISTS `car` (
`serialNumber` varchar(255) NOT NULL,
`cc` int(11) NOT NULL,
`l100` double DEFAULT NULL,
`nameCar` varchar(255) DEFAULT NULL,
PRIMARY KEY (`serialNumber`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `driver` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`age` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
CREATE TABLE IF NOT EXISTS `have` (
`driver_id` int(11) NOT NULL,
`car_serialNumber` varchar(255) NOT NULL,
PRIMARY KEY (`driver_id`,`car_serialNumber`),
KEY `fk_driver_has_car_car1_idx` (`car_serialNumber`),
KEY `fk_driver_has_car_driver_idx` (`driver_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `have`
ADD CONSTRAINT `fk_driver_has_car_driver` FOREIGN KEY (`driver_id`) REFERENCES `driver` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
ADD CONSTRAINT `fk_driver_has_car_car1` FOREIGN KEY (`car_serialNumber`) REFERENCES `car` (`serialNumber`) ON DELETE NO ACTION ON UPDATE NO ACTION;
As you see, "have" is mapping table

Hibernate not setting reference column

I'm using hibernate 4.3.7.Final on OSX with Mysql 5.5.8.
I have a joinTable relationship setup however my foreign keys fail to add:
[ERROR] org.hibernate.tool.hbm2ddl.SchemaExport - HHH000389: Unsuccessful: alter table T_USER_AUTHORITY add constraint FK_fr51fcyulxn31ijiotp4fx7i5 foreign key (email) references T_USER
[ERROR] org.hibernate.tool.hbm2ddl.SchemaExport - Can't create table 'carcloud.#sql-149c1_195' (errno: 150)
if I run SHOW ENGINE INNODB STATUS; I get the following:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
141106 5:48:00 Error in foreign key constraint of table carcloud/#sql-149c1_123:
foreign key (email) references T_USER:
Syntax error close to:
if i run:
alter table T_USER_AUTHORITY add constraint FK_fr51fcyulxn31ijiotp4fx7i5 foreign key (email) references T_USER (email);
The constraint is successfully added, note (email) at the end which is the referencing column.
It is set as my primary key:
CREATE TABLE `T_USER` (
`email` varchar(100) NOT NULL,
`created_by` varchar(50) NOT NULL,
`created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`last_modified_by` varchar(50) DEFAULT NULL,
`last_modified_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`OPT_LOCK` int(11) DEFAULT NULL,
`first_name` varchar(50) DEFAULT NULL,
`last_name` varchar(50) DEFAULT NULL,
`password` varchar(100) DEFAULT NULL,
`phone` varchar(100) NOT NULL,
PRIMARY KEY (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Any ideas?
The only difference that i see is in Hibernate "references T_USER" and in sql "references T_USER (email)" so you should insert java code that call "alter table T_USER_AUTHORITY add constraint FK_fr51fcyulxn31ijiotp4fx7i5 etc .. "

HQL is generating incomplete 'cross join' on executeUpdate

I am working on a grails project. I have following query that I am trying to execute
String CHECK_FOR_HIGH_TRADE_VOLUME_QUERY = "Update LocationTrade lt set lt.hasVeryHighVolume=true where lt.locationIndices=? AND lt.trade.volume>20000";
...
LocationTrade.executeUpdate(CHECK_FOR_HIGH_TRADE_VOLUME_QUERY, [indices]);
The relationship between LocationTrade and Trade is unidirectional many-to-one. So, LocationTrade has a reference to Trade but Trade class does not have reference to the List of LocationTrade.
On execution, I get the following exception.
org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute update query; SQL [update location_trade cross join set has_very_high_volume=1 where location_indices_id=? and volume>20000]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute update query
and
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'set has_very_high_volume=1 where location_indices_id=997 and volume>20000' at line 1
It seems that generated query is wrong. There should have been a join with the Trade table, but that is missing. I am unable to identify the error that I made here. Can some of you help me?
Creation Script for the two tables (I have stripped some of the uninteresting columns)
CREATE TABLE `location_trade` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`auto_status` varchar(255) DEFAULT NULL,
`exclusion_reason_description` varchar(255) DEFAULT NULL,
`exclusion_reason_id` bigint(20) DEFAULT NULL,
`exclusion_reason_title` varchar(255) DEFAULT NULL,
`location_indices_id` bigint(20) DEFAULT NULL,
`manual_status` varchar(255) DEFAULT NULL,
`trade_id` bigint(20) DEFAULT NULL,
`absolute_price` decimal(19,6) DEFAULT NULL,
`flag` varchar(255) DEFAULT NULL,
`auto_exclusion_reason` varchar(255) DEFAULT NULL,
`date_created` datetime DEFAULT NULL,
`exclusion_reason_text` varchar(255) DEFAULT NULL,
`last_updated` datetime DEFAULT NULL,
`has_very_high_volume` bit(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK858985A90CAA966` (`location_indices_id`),
KEY `FK858985AB5FA6A69` (`trade_id`),
CONSTRAINT `FK858985A90CAA966` FOREIGN KEY (`location_indices_id`) REFERENCES `location_indices` (`id`),
CONSTRAINT `FK858985AB5FA6A69` FOREIGN KEY (`trade_id`) REFERENCES `trade` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=25405 DEFAULT CHARSET=latin1;
CREATE TABLE `trade` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`version` bigint(20) NOT NULL,
`comments` varchar(1020) DEFAULT NULL,
`end_date` datetime DEFAULT NULL,
`price` decimal(19,6) DEFAULT NULL,
`price_type` varchar(255) DEFAULT NULL,
`source_id` bigint(20) DEFAULT NULL,
`start_date` datetime DEFAULT NULL,
`trade_date` datetime DEFAULT NULL,
`trade_name` varchar(255) DEFAULT NULL,
`volume` decimal(19,6) DEFAULT NULL,
`volume_units` varchar(255) DEFAULT NULL,
`date_created` datetime DEFAULT NULL,
`last_updated` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FK697F1642D085935` (`source_id`),
CONSTRAINT `FK697F1642D085935` FOREIGN KEY (`source_id`) REFERENCES `job_source` (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=26567 DEFAULT CHARSET=latin1;
Thanks
The Hibernate documentation says:
No join, either implicit or explicit, can be specified in a bulk HQL query. Sub-queries can be used in the where-clause, where the subqueries themselves may contain joins.
lt.trade.volume is an implicit inner join between LocationTrade and Trade, so the query is invalid. You'll have to rewrite it to something like the following:
update LocationTrade lt set lt.hasVeryHighVolume=true where lt.locationIndices=?
and lt.id in (
select lt2.id from LocationTrade lt2 where lt2.trade.volume > 20000)
Or you'll have to use a SQL query instead.

Categories

Resources