How to Get DB Field name from ConstraintViolationException - Hibernamte - java

How to get the Name of the DB field causing ConstraintViolationException while inserting in to Database in hibernate.
I have the Table Like
mysql> desc Mytable;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | bigint(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | UNI | NULL | |
| city | varchar(20) | YES | UNI | NULL | |
+-------+-------------+------+-----+---------+----------------+
And records inthe table are
mysql> select * from Mytable;
+----+--------+-------+
| id | name | city |
+----+--------+-------+
| 1 | SATISH | BLORE |
+----+--------+-------+
1 row in set (0.00 sec)
Now, im trying to insert
"RAMESH","BLORE" through hibernate.
It is throwing ConstraintViolationException due to "BLORE" (CITY) already Exist.
if im trying to insert.
"SATISH","MLORE" through hibernate
It is throwing ConstraintViolationException due to "SATISH" (NAME) already Exist.
My question is
how to get fieldName who is causing the exception ConstraintViolationException through Hibernate.

Since there might be other constraints that could be violated (e.g. combined keys), you only have the name of the constraint that is violated, which in your case might just be the column name (however, I'm not entirely sure about that). You can get the name of the violated constraint by calling getConstraintName() on the ConstraintViolationException.

Related

ERROR 1366 (HY000): Incorrect string value: '\x85\x8A\x8D\x95\x97' for column 'name' at row 1

this is the faulty statement:
insert into customer (id, uuid, name) values (1,uuid(), 'àèìòù');
I am using MySQL server 8.0.32 (just upgraded from 5.7) on Windows.
I am also executing this statement from MySQL client, on the same machine.
Same error using mysql-connector-j-8.0.32.
jdbc:mysql://localhost:3306/risk?allowPublicKeyRetrieval=true&useLocalSessionState=true&rewriteBatchedStatements=true
No error using mysql-connector-java-8.0.22 with the same environment and the same connection string.
This the table:
| customer | CREATE TABLE `customer` (
`id` bigint NOT NULL,
`uuid` char(36) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UK_q8w2f8xfdoax44qc8w0epholu` (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
And these are the variables:
mysql> show variables like '%char%';
+--------------------------+------------------------------------------------------+
| Variable_name | Value |
+--------------------------+------------------------------------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8mb3 |
| character_sets_dir | D:\shape\servers\mysql-8.0.32-winx64\share\charsets\ |
+--------------------------+------------------------------------------------------+
8 rows in set (0.00 sec)
mysql> show variables like '%collation%';
+-------------------------------+--------------------+
| Variable_name | Value |
+-------------------------------+--------------------+
| collation_connection | utf8mb4_0900_ai_ci |
| collation_database | utf8mb4_0900_ai_ci |
| collation_server | utf8mb4_0900_ai_ci |
| default_collation_for_utf8mb4 | utf8mb4_0900_ai_ci |
+-------------------------------+--------------------+
4 rows in set (0.00 sec)
Maybe a bug? Am I missing something?
update
this is working:
mysql> set character_set_client=cp850;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into customer (id, uuid, name) values (1,uuid(), 'àèìòù');
Query OK, 1 row affected (0.00 sec)
But why?
And how can I use UTF-8 also on client side?
update2
Also, commenting in my.ini:
character-set-server=utf8mb4
collation-server=utf8mb4_0900_ai_ci
#character-set-client-handshake = FALSE
#init_connect='SET NAMES utf8mb4'
makes JDBC working again...
What application are you using?
Apparently, your client is using "cp850" since that hex decodes to àèìòù.
You could either tell MySQL that you are using cp850 by establishing the connection that way, or (better) fix the encoding inside the client.
That is, the problem does not seem to be with MySQL.
More
If you are using Windows, did you do something like
chcp 850
Instead, you need
chcp 65001

MySQL - Selecting only the default value from column

I am wondering is it possible to select only the default value of empty column?
I have absolutely empty table and I want just to select one of the columns default value - it is important for my JAVA app which is filling the table.
Thanks.
You can get the default from the INFORMATION_SCHEMA.COLUMNS
select COLUMN_DEFAULT
from INFORMATION_SCHEMA.COLUMNS
where TABLE_SCHEMA='your_db' and TABLE_NAME='your_table' and COLUMN_NAME='your_column'
You can define a default value for a column when you create a table, if you just want MySQL to insert it automatically:
create table my_table (i INT DEFAULT 1);
But if you mean you want the default value which is stored in the DB dictionary, you can get it by this query:
SELECT Column_Default
FROM Information_Schema.Columns
WHERE Table_Schema = 'yourSchema'
AND Table_Name = 'yourTableName'
AND Column_Name = 'yourColumnName'
I can only think of two ways:
Inserting a row
Insert a row without specifying a value for that column
Select the column from that row; it will have the default value of the column
Delete the row
...probably all in a transaction so nothing else sees it.
Using describe (explain)
The describe command (aka explain) describes objects in the system, including tables. So if you do explain YourTable, you'll get back information about the table, including its default values.
Here's an example from that linked documentation:
mysql> DESCRIBE City;
+−−−−−−−−−−−−+−−−−−−−−−−+−−−−−−+−−−−−+−−−−−−−−−+−−−−−−−−−−−−−−−−+
| Field | Type | Null | Key | Default | Extra |
+−−−−−−−−−−−−+−−−−−−−−−−+−−−−−−+−−−−−+−−−−−−−−−+−−−−−−−−−−−−−−−−+
| Id | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | | | |
| Country | char(3) | NO | UNI | | |
| District | char(20) | YES | MUL | | |
| Population | int(11) | NO | | 0 | |
+−−−−−−−−−−−−+−−−−−−−−−−+−−−−−−+−−−−−+−−−−−−−−−+−−−−−−−−−−−−−−−−+
So you can extract the default from the Default column in the returned rows.
Ah, of course, there's a third way, see slaakso's answer for it.

Spring JPA OneToMany with composite Key mapping

I am having issues mapping the following using spring JPA. Let's say I have a order table which has two primary keys. one is a foreign key to customer and another is a foreign key to order Type as seen below:
Customer
+----+------+--+
| id*| name | |
+----+------+--+
| 1 | Joe | |
+----+------+--+
Order
+------------+-------------+
| customerId | orderTypeId |
+------------+-------------+
| 1 | 1 |
+------------+-------------+
OrderType
+----+--------+
| id | type |
+----+--------+
| 1 | online |
+----+--------+
the idea is each customer has a one to many relationship with Orders. the primary key of orders is a combination of the two foreign keys.
any help would be appreciated.

Define timestamp in hibernate.hbm.xml

I have a dummy table I want to map with Hibernate can you please help me to define in dummy.hbm.xml
type=timestamp, Default=CURRENT_TIMESTAMP, extra=on update CURRENT_TIMESTAMP
And which type of variable should i need to define in java class?
desc dummy;
+------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+-------------------+-----------------------------+
| timestamp | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+------------+--------------+------+-----+-------------------+-----------------------------+

Many SQL select queries in java with possibility of not finding

I currently got a performance issue with an application that uses many sql select.
The programming language is java and I'm using a mysql database. It contains about 10 million records.
What it needs to do is to find records in a database with zipcode and house number as parameters. When it does not find a record, it needs to do a query with only the zipcode and get the record with the lowest house number. When the zipcode cannot be found in the database the application needs to deal with this.
Thus the code for doing single queries looks like this:
Statement select = "select * from zipcode_addresses where zipcode = ? and houseNo =?";
ResultSet rs = select.executeQuery();
if(rs.next()) {
dealWithResult(rs);
}
else {
Statement alternativeSelect = "select * from zipcode_addresses where zipcode = ? group by houseNo having min(houseNo)";
ResultSet rs = alternativeSelect.executeQuery();
if(rs.next()) {
dealWithResult(rs);
} else {
System.err.println("Could not find zipcode :" + zipcode);
}
}
Is there a proper way of doing batch select queries which deals with data not being found?
Thanks!
Update
The table structure is the following:
+-----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| zipcode | varchar(6) | NO | PRI | NULL | |
| house_no | int(11) | NO | PRI | NULL | |
| sanddcode | varchar(45) | NO | | NULL | |
| depot | varchar(3) | NO | | NULL | |
| network_point | varchar(6) | NO | | NULL | |
| region | varchar(3) | NO | | NULL | |
| seq | int(11) | NO | | NULL | |
| cluster_id | varchar(1) | NO | | NULL | |
| strand_id | int(11) | NO | | NULL | |
| strand_props_id | int(11) | NO | | NULL | |
| version_id | int(11) | NO | PRI | NULL | |
+-----------------+-------------+------+-----+---------+-------+
Primary key on version id, zipcode and house_no
Index on zipcode and house_no and another index on zipcode, both using BTREE index.
The application might sometimes be used to do 1 million distinctive select queries at which point it just takes too long.
Your code snippet doesn't show how your statements are being prepared. If your statements are being called numerous times then you should take a look at the PreparedStatement object:
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
Your statements can then be cached to reduce future overhead.
you could create a stored procedure with two parameters, and use the House Number as optional, or just let that the procedure finds if exists or don't.
A lot depends on the usage pattern. How many queries you run, how often there is a ZIP code miss, etc. First off, I would use PreparedStatements where posssible. I am not that familiar with MySQL, but they are usually cached and reused by the connection-database, that will help with performance. Next, If ZIP code misses were common, I would probably build an in memory cache of ZIP codes to short circuit doing 3 queries on a miss. After that, I might make a view that's ZIP + house number. Going further depends more on how your appliation works, but these things would help.
The 'group by' in your second SQL query is unnecessary and killing performance. For maximum performance, replace this select (the second one in your code) ...
select * from zipcode_addresses where zipcode = ?
group by houseNo having min(houseNo)
with this ...
select min(houseNo) from zipcode_addresses where zipcode = ?
Also, ensure you have an index on zipcode + houseNo (which it looks like you have - from the updated post).

Categories