Adding Schema name to entity in Spring data? - java

I am getting an error when using an Oracle DB and Spring Data. The error is:
ORA-00942: table or view does not exist
The cause of this error is that the user I am connecting with does not have access to the tables in the schemas I wish to connect to.
I read that 2 fixes to this are to create synonyms in my database or to specify the schema that each entity/table belongs to.
I am going to try the Schema approach first. How do I do so?
My example entity below, a Dog in the Vet Schema:
#Entity
#Table(name = "Dog")
public class Dog
{
#Id
private String id;
#Column(name = "NAME")
private String name;
#Column(name = "Owner")
private String owner;
//getters and setters etc...

The #Table annotation provides the schema attribute:
#Table(name = "Dog", schema = "Vet")

You must prefix your tables with the schema name and with a . inbetween them:
#Table(name = "VET.Dog")

Related

Hibernate auto-update does not create table for specific entity

I have a Java Spring MVC app using Hibernate and a MySQL 5.7 DB. Hibernate is configured to automatically update the schema from new entities via: <prop key="hibernate.hbm2ddl.auto">update</prop>
It is working for all the entities in my app except for one:
#Entity
#IdClass(QuestionId.class)
#Getter
#Setter
#Accessors(chain = true)
#EqualsAndHashCode
public class Question {
#Id
private String key;
#Id
private Long version;
#Type(type = "json")
#Column(columnDefinition = "json")
private JsonNode metaData;
}
This entity is defined in exactly the same way as other entities, but when the app starts, this particular table does not get created in the DB. There are no error messages given that I have been able to uncover.
I actually discovered the problem with help from an answer to a different question: hibernate not creating table but no error messages
This behavior can happen when using reserved db keywords as property/column names. In my case, key is a reserved keyword in MySQL: https://dev.mysql.com/doc/refman/8.0/en/keywords.html
public class Question {
#Id
private String key; // <==== NO; `KEY` is a db reserved keyword.
#Id
private Long version;
#Type(type = "json")
#Column(columnDefinition = "json")
private JsonNode metaData;
}
Changing the property name (or alternatively specifying an explicit column name) fixes the issue. There may have been an error message if I enabled the right debugging flags, but the problem was solved before then.

Hibernate/JPA persist OneToMany objects with generated UUID's

I have been using Hibernate a lot but using Hibernate/JPA with UUID got me stumped a bit. I am using hibernate 5.2.12.Final.
I have an object called TimePeriod with this mapping:
#Entity(name = "time_period")
public class TimePeriod extends AbstractDomainObject {
#OneToMany(mappedBy = "timePeriod", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<TimePeriodBlock> timePeriodBlocks = new ArrayList<>();
...
public void addTimePeriodBlock(TimePeriodBlock timePeriodBlock) {
timePeriodBlock.setTimePeriod(this);
this.timePeriodBlocks.add(timePeriodBlock);
}
...
With the following child relationship:
#Entity(name = "time_period_block")
public class TimePeriodBlock extends AbstractDomainObject {
...
#ManyToOne
#JoinColumn(name = "time_period_id", nullable = false)
private TimePeriod timePeriod;
...
They share this super class:
#MappedSuperclass
public abstract class AbstractDomainObject {
...
#Id
#GeneratedValue
#Column(name = "id", columnDefinition = "uuid", updatable = false)
private UUID id;
...
When I execute the following:
// pseudo code
TimePeriod t = new TimePeriod();
t.setName("test");
TimePeriodBlock b = new TimePeriodBlock();
t.addTimePeriodBlock(b);
em.persist(t);
I get the exception:
...
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value : test.TimePeriodBlock.timePeriod
...
Some notes:
I strongly believe that this could be because Hibernate generates the UUID (and not the database) but, since I am not sure, I hope some fellow Developer might know how this could work.
I am using PostgreSQL 9.6 and the database can also generates UUIDv4 but requires compiling an extra extension so I opted for Hibernate to generate it.
When I enter some data in the database and retrieve the data it is fetched without any error.
Storing other objects without #ManyToOne relationships do store without any error and have a UUID that is generated by Hibernate.
Well after some debugging and using Luay Abdulreheem suggestion I found out that hibernate is working just fine; in this case my objects are send using a REST interface (using Jackson) and the reference to the parent was lost as the unmarshalling of the JSON is done using fields.
So nothing to see here, move along...

How to model lookup tables JPA

I'm trying to build a Spring Boot data layer on top of another project's DB. I'm want to get to a point where I can consume their data via Restful endpoints rather than directly from the DB. Maximum abstraction is the goal. Here's my problem. Consider the following JPA entity:
#Entity
#Table(name = "PERSON", schema = "public")
public class Person {
#Id private long id;
private String name;
private long favoriteFood;
private Address address;
//Getters, Setter etc.....
}
Notice that favoriteFood is a long, not a String. This is because the DB uses a lookup table. Let's say Joe's favorite food is pizza. The person table stores a 1 in the favorite_food column which is the fk to the "pizza" value stored in the food_ref table. This pattern is repeated hundreds or times in the DB. What is the best way to model this in JPA/Hibernate? Change the variable to String and have the getter and setter do the lookup? I've not found any examples which seems strange. This is a common DB structure. Any advice on best practices would be appreciated. Thanks!
The best way in this scenario is to use one to one relationship in the JPA entity with the FoodRef class
#Entity
#Table(name = "PERSON", schema = "public")
public class Person {
#Id private long id;
private String name;
#OneToOne(fetch=FetchType.LAZY)
#JoinColumn(name="food_ref_id")
private FoodRef favoriteFood;
private Address address;
//Getters, Setter etc.....
}

Hibernate Unidirectional OneToMany Not Working with composite id

I've been bashing my head on my keyboard for two days trying to figure this out...
Some background: We have a data model set up with a Perl code base that runs straight native SQL statements to the database via ODBC. For certain reasons, we decided to rewrite the code in Java... I thought it would be a good idea to use Hibernate to define all of the mappings. We don't want to edit the data model.
For simplicity sake, I can express the problem with only part of our data model. We have the entities "Job","JobDatabase" and "JobTable".
Job has a PK of job_name. Database has a PK of job_name,name. Table has a PK of job_name,src_database_name,name. As you may expect, Job has a OneToMany relationship with JobDatabase, and Database has a OneToMany with JobTable.
For purposes of this test, I'm starting with empty tables and trying to create some sample data. I can insert a Job and a JobDatabase, but when I try to insert the JobTable, Hibernate throws an error. Or more accurately, that is where it complains. It doesn't start executing my code because it detects the mapping error. However, if I remove the association between JobDatabase and JobTable, it will insert all Job and JobDatabase records correctly with no errors.
Sample Classes (all fields have getters/setters... there are also many other fields):
#Entity
#Table(name="Job")
public class Job implements Serializable {
#Id
#Column(name="job_name",nullable = false)
private String jobName;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "job_name", referencedColumnName = "job_name")
private Set<JobDatabase> databases;
}
#Entity
#Table(name="JobDatabase")
public class JobDatabase implements Serializable {
#Id
#Column(name="job_name",nullable = false)
private String jobName;
#Id
#Column(name="name",nullable = false)
private String name;
#OneToMany(cascade = CascadeType.ALL)
#JoinColumns({
#JoinColumn(name = "job_name", referencedColumnName = "job_name"),
#JoinColumn(name = "name", referencedColumnName = "src_database_name")
})
private Set<JobTable> tables;
}
#Entity
#Table(name="JobTable")
public class JobTable implements Serializable{
#Id
#Column(name="job_name",nullable = false)
private String jobName;
#Id
#Column(name="src_database_name",nullable = false)
private String srcDatabaseName;
#Id
#Column(name="name",nullable = false)
private String name;
}
The error:
Exception in thread "main" org.hibernate.MappingException: Unable to find column with logical name: src_database_name in JobDatabase
I keep getting this error. I do not understand why it is looking for the referenced column in the entity "owning" the mapping. src_database_name does indeed only exist in JobTable - it is referred to as "name" in JobDatabase. JobTable also has a "name" field, but it refers to the name of the Table.
You need to have src_database_name column in your JobDatabase table. Or you can change src_database_name to other column name.
For composite key reference column must be present in your source table.

Hibernate ManytoOne mapping deleting child when parent does not exists

I have one java class Specification which is getting deployed to Specs master table.
#Entity
#Table(name = "SPECS_MASTER")
Specification
{
#Id
#Column(name = "SPEC_ID")
String specId;
//other attribute
}
Another Class
#Entity
#Table(name = "PRODUCT_SPECS")
public class SpecificationValue {
#Id
#Column(name = "NODE_SPECS_ID")
private Integer specId;
#ManyToOne()
#JoinColumn(name = "SPEC_ID")
private Specification specification;
//other mappings and attribute
}
My problem here is when I am deleting a specification_value by hibernate, if Specs master does not exists than hibernate is not able to delete specification value entry, which is expected in this mapping.
I want to be able to delete specification values even if specs_master does not exits, is there any way I can do this?

Categories