Spring JPA does not detect deleted tables - java

I deleted my tables to let them be recreated by Spring JPA, but spring does not create them. Instead, I'm getting the following exception:
Unable to create unique key constraint (guild_id, setting_key) on table guild_setting: database column 'guild_id' not found. Make sure that you use the correct column name which depends on the naming strategy in use (it may not be the same as the property name in the entity, especially for relational types)
I don't know why I get this error, but before I deleted the tables in the database, the column name was guild_id, so what JPA says is not right.
This is an excerpt of the Entity:
#Entity
#Table(uniqueConstraints=#UniqueConstraint(columnNames={"guild_id", "setting_key"}))
public class GuildSetting extends Setting {
#Column(nullable = false)
private long guildId;
The following properties are set with the spring.datasource properties:
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update

If you don't want to use #Column(name="guild_id")
You should use #UniqueConstraint(columnNames={"guildId", ...}
The generated table will contain the (correct) column, named guild_id
#Entity
#Table(uniqueConstraints=#UniqueConstraint(columnNames={"guildId", "setting_key"}))
public class GuildSetting extends Setting {
#Column(nullable = false)
private long guildId;
Agreed, this looks like a bug...
Note: You did not mention you have problems with the setting_key unique constraint.
Do you use #Column(name="setting_key") or private String setting_key?

Related

Hibernate JPA uniqueness

Let's say that this is a class that has unique constrained field.
#Entity
public class Thing {
#Column(name = "name", unique = true)
private String name;
#ManyToOne
private Owner owner;
}
Example works just fine if new Things are created with unique names. But when different owners want to create things with the same name this approach fails.
Is it possible to set unique constraint to differ records of Things in the database based on the Owners using Hibernate/JPA functionalities (I could not find any) or should I write my own logic and dump the unique from #Column.
Perhaps it could be done with Hibernate Validator? Reading the docs I haven't found much about unique constraints.
You're looking for #UniqueConstraint
http://docs.oracle.com/javaee/5/api/javax/persistence/UniqueConstraint.html

Hibernate - column name external configuration

We have a requirement where we need to have the column names externally configurable in Hibernate. The column names in the database will change in the future and we do not want to change the hibernate entity class (annotations) every time this happens.
What is the best approach for this scenario?
You cna either use a custom NamingStrategy (see here)
Or define dynamic maping (see here)
You can use hibernate mappings files
Check this link maybe it can help you
http://www.tutorialspoint.com/hibernate/hibernate_map_mapping.htm
You can keep column names in some class as constants, this way you would only need to update that class when column names change
public class MyEntityColumns {
public static final String COLUMN1 = "column1";
...
}
#Entity
public class MyEntity {
#Column(name = MyEntityColumns.COLUMN1)
private String someField;
}

Hibernate Inheritance.JOINED generated FK name

I am currently trying to use inheritance within Hibernate and came across InheritanceType.JOINED. I like the idea of concentrating all data in one table and sharing IDs rather than having duplicate columns in all the sub type tables (#MappedSuperClass). But Hibernate automatically generates indexes on my sub class tables on the id column like FK_idx3wiwdm8yp2qkkddi726n8o everytime I initialize my Hibernate singleton. I noticed that by hitting the 64 key limit on my MySQL Table as the names are generated differently on every startup.
What is the proper way to handle this? Can this be fixed by annotations? What else could I try?
I know that there are countless similar Questions on SO but haven't been able to identify one solving my specific problem.
I am not going to disable hbm2ddl.auto during dev mode.
I am using MyISAM. There are no actual Foreign Keys. This is why Hibernate generates default indexes, I think. Anyway, the problem would be identical with InnoDB and real Foreign Keys as the names would still be quite random. Or maybe Hibernate would actually check for existence in this case. I don't really see, why it does not do this on MyISAM tables.
As I hit similar problems before, the solution could also be to specify a name for that single-column index. But how?
Super Class: FolderItem
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class FolderItem implements Comparable<FolderItem>
{
#Id
#GeneratedValue
protected int id;
protected String name;
#OneToOne
#ForeignKey(name = "fkParent")
protected Folder parent;
...
}
Sub Class: Folder
#Entity
public class Folder extends FolderItem
{
#OneToMany(mappedBy = "parent")
#OrderBy(value = "sortOrder")
private List<FolderItem> children;
...
}
What I tried
add #Index to FolderItem.id - this created an index on the FolderItem table as one would expect, but didn't affect the Folder table
copy protected int id; to Folder and tried to add an #Index to it, which resulted in an Exception similar to "duplicate definition of ID"
add #Table(appliesTo = "Folder", indexes = { #Index(name = "fkId", columnNames = { "id" }) }) to Folder class, which actually created my specified index as expected, but still created it's own FK_9xcia6idnwqdi9xx8ytea40h3 which is identical to mine, except for the name
Try #PrimaryKeyJoinColumn(name = "foler_item_id") annotation for Folder class.

Hibernate returns only one result (After changing table names)

I am using hibernate retrieve results from my MySQL database into my Java project. Recently, I had a lot of redundant data and had to manually clean up the database by copying the required data into new tables and then renaming the newly created table to old table.
But, now querying the database with hibernate gives only one row as the result. I have manually checked the database and there are several different rows in the database. My query to Hibernate is something like this:
Criteria c = session.createCriteria(UserDto.class);
c.setMaxResults(100);
List<UserDto> users = c.list();
users contains 100 elements but all are the same.
The mapping of userDto is here.
Any idea what is happening here?
If your UserDto class has ToMany relations, then this is quite possible that outer join on them results in many records which all contain one and the same user data. You should use
session.createCriteria(UserDto.class).setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
Double-check your mapping of the UserDto class to the database.
My guess is that you don't have it mapped to the table that you think you do.
As Sebastien mentioned, setting hibernate.show.sql to true should make this obvious.
Did you deleted the old tables? And in the configuration file what is the value for "hibernate.hbm2ddl.auto"?
I think the reason is these records have same id, so Hibernate treat them as the same record. You can check it.
I had same problem. In my case, the problem detected when I created a table in MySQL manually and I tried to read data from that table using hibernate and a dto class. After checking my dto class fields and database table, I figured out that there is a difference between table column named "id" and the class field which named dbId. The code was something like this:
#Id
#GeneratedValue
#Column(name="db_id", unique = true)
private long dbId;
So I edited the name and changed the code:
#Id
#GeneratedValue
#Column(name="id", unique = true)
private long dbId;
Which "id" was the correct name of databse table column and the problem has been solved.

Problem using #SecondaryTable in Hibernate

Abridged version of my schema:
utility_company
id int not null -- PK
name varchar(255) not null
utility_settings
utility_id -- FK to utility
use_magic tinyint(1) not null default 0
There is a one-to-one mapping between these two tables. Setting aside the fitness of this design, I want to Map the data in both of these tables to one object. In Hibernate/JPA, this is allegedly done as follows:
#Entity
#Table(name = "utility_company")
#SecondaryTables({
#SecondaryTable(
name = "utility_settings",
pkJoinColumns = {
#PrimaryKeyJoinColumn(
name="utility_id", referencedColumnName="id")
})
})
public class UtilityCompany extends AbstractEntity {
And so forth.
Every #Column includes the appropriate table name.
When I deploy, I get this error:
Cannot find the expected secondary table:
no utility_company available for poscore.model.UtilityCompany
The utility_company table is definitely there (a previous version only maps UtilityCompany to the utility_company table; I'm adding the utility_settings).
Found numerous forum posts with this exact problems and no answers. I've also tried various allegedly legal forms of specifying the #SecondaryTable all of which have the same effect.
Anyone successfully use #SecondaryTable, and, if so, seen this?
"Every #Column includes the appropriate table name."
Try removing the explicit table name for the first table name columns, only specifying it for the secondary table columns. Did the trick for me.
Your mappings are correct IMHO, and runs fine with DataNucleus AccessPlatform as the JPA implementation. Maybe Hibernates log tells you more ?
--Andy DataNucleus

Categories

Resources