How do I map Hibernate collections with Oracle's NOT NULL column constraint enforced? - oracle

I have 2 tables, ENQUIRY and ELEMENT with a One-to-Many relationship such that an Enquiry has many Elements.
I would like to enforce Oracle's NOT NULL constraint on foreign key column ELEMENT.ENQUIRY_ID as this is best-practice. I have the following collection on the Enquiry object:
#OneToMany(cascade = CascadeType.ALL)
#JoinColumn(name = "ENQUIRY_ID", referencedColumnName = "ID")
private Set<Element> elements = new HashSet<Element>();
When I enforce the NOT NULL constraint I receive the following stacktrace:
Caused by: java.sql.BatchUpdateException: ORA-01400: cannot insert NULL into ("ELEMENT"."ENQUIRY_ID")
So Hibernate is obviously persisting the collection of elements before the parent enquiry and then going back and doing an UPDATE on the foreign key field afterwards.
Is there a way to enforce the NOT NULL constraint on the collection foreign key field?

Have you tried nullable = false in #JoinColumn?

Related

Check ManyToOne eager and lazy relations for null

Suppose that a certain booking's invoice is null in the DB.
public class Booking {
#Id
private Integer id;
...
#ManyToOne(... fetch = FetchType.LAZY)
#JoinColumn(...)
private Invoice invoice;
}
It seems that a many-to-one lazy relation always creates a proxy object for booking.getInvoice(), while an eager relation would just return a null. I think I can check the booking.getInvoice().getId(), but for that I must be sure that the relation is lazy. I don't want to do that because it forces me to always track the relation fetch type in the client code.
What if I have a lot of existing code that checks null in 'eager mode' and I want to convert a certain relation to lazy? Do I have to convert all null checks for that relation as well?
I'd think that since the DB field is null then the JPA would be smart enough to not create the proxy object at all here, leaving the private field invoice null.
Is the double check for null and id the only way to go?
Invoice invoice = booking.getInvoice();
if (invoice != null && invoice.getId() > 0) {
...
}
Is there a fetch-type-independent way to check for null many-to-one children in JPA?

Error on JPA many-to-many relationship between entity table and join table

I want a many-to-many relationship between an entity table and a join table. Invoices consist of a set of subscriptions. A subscription can be a part of multiple invoices (e.g. monthly subscription). Subscriptions consist of a user and a service. I am already using the subscriptions table as a join table for the many-to-many relationship between users and services (e.g. a user can subscribe to multiple services and a single service has multiple users). I have a table, "invoice_subscription," with IDs for both the invoice and subscription. Every table has its own ID. Below is the relevant snippet in the invoice object:
#ManyToMany
#JoinTable(
name = "invoice_subscription",
joinColumns = #JoinColumn(name = "invoice_id"),
inverseJoinColumns = #JoinColumn(name = "subscription_id")
)
public Set<Subscription> getSubscriptions() {
return subscriptions;
}
I am using the following in the subscription object:
#ManyToMany(mappedBy = "subscriptions")
public Set<Invoice> getInvoices() {
return invoices;
}
For the above, I am receiving the error below:
org.hibernate.MappingException: Foreign key (FKfe5yu82iapjynsdyfitclkri4:invoice_subscription [subscription_id])) must have same number of columns as the referenced primary key (subscription [user_id,service_id])
When I switch to two "#JoinColumn" annotations with the IDs in the error, I get the following error:
org.hibernate.AnnotationException: A Foreign key refering com.example.model.Subscription from com.example.model.Invoice has the wrong number of column. should be 1
I agree with this, but it seems to contradict the previous error. I've read documentation, guides, and other questions, but I have not found any useful information. I'm clearly missing something obvious.

Spring Boot with Vaadin - using foreign keys

I am new to Spring Boot and Vaadin. I followed a tutorial to create CRUD pages for a phone book application however I am having trouble using foreign keys. I have a Contact table which has phone type (i.e. cell or home) as a foreign key - i.e. it is referenced to my PhoneType table. I am stuck on how to populate the phone type from a drop down of values populated in my PhoneType table. Right now I am I have the following member variable in my Contact class
#ManyToOne
#JoinColumn(name="type")
private PhoneType phoneType;
And in my PhoneType class I have
#Column(name = "type")
private String phoneType;
However I am getting an error that says "Error executing DDL via JDBC Statement".
The rest of the application works well with the CRUD pages.
Firstly in mySQL implementations you can't store actual objects unless you use 8.0+ JSON data type. SQL has no idea what a PhoneType is because it's an object and not a valid data type. https://www.w3schools.com/sql/sql_datatypes.asp
If you want to store actual objects you need to find a noSQL implementation that you like.
So your "Customer" class doesn't map to a table properly. You would need to make instance variables such as
String hasCellPhone, hasHomePhone; //etc for the options in your dropdown menu
instead of trying to put a phonetype object.
I asked almost the exact same question, I suggest you read this entire thread.
https://stackoverflow.com/a/50879597/5468597
create table item (
barcode bigint not null auto_increment primary key,
name varchar(20) not null,
type varchar(20) not null,
is_available boolean not null,
is_late boolean null,
notes varchar(255) null,
check_out_date datetime null,
due_date datetime null
#create index idx_barcode (barcode));
create table patron (
trinity_id bigint not null primary key,
name varchar(30) not null,
email varchar(20) not null,
owes_fines boolean not null,
fines_owed int null
#create index idx_trinity_id (trinity_id));
create table checked_out_items (
ref_id bigint primary key auto_increment not null,
patron_id bigint not null,
item_id bigint not null,
item_available boolean not null,
item_check_out_date datetime null,
item_due_date datetime null);
alter table checked_out_items
add constraint fk_patron_id
foreign key (patron_id) references patron(trinity_id),
add constraint fk_item_id
foreign key (item_id) references item(barcode)
#add constraint fk_item_available
#add constraint fk_check_out_date
#add constraint fk_due_date
#foreign key (item_available references item(is_available)
#foreign key (item_check_out_date) references item(check_out_date)
#foreign key (item_due_date) references item(due_date)
on update cascade
on delete cascade;
insert into patron values(0000000,'Test Erino','test#erino.edu',0,null);
insert into item values(1,'Chromebook','Laptop',0,null,null,null,null);
insert into checked_out_items(patron_id,item_id,item_available,item_check_out_date,item_due_date)
select patron.trinity_id,item.barcode,item.is_available,item.check_out_date,item.due_date
from patron
inner join item;
and lastly:
select * from item;
select * from patron;
select * from checked_out_items;
I won't post the java logic here. That's for you to read in the other thread.
I solved my question.
#ManyToOne (cascade = {CascadeType.ALL})
#JoinColumn(name="phoneType_typeId")
private PhoneType phoneType;
And
#Id
#GeneratedValue
#Column(name = "typeId")
private Long id;

Foreign key constraint fails on nullable field

I have a table organizations. This table has a primary id (int 10, unsigned, AUTO_INCREMENT).
In the table organizations, I also have a foreign key to the iself: main_organization_id. This has the following attributes: (int 10, unsigned, nullable, empty:TRUE, default:NULL).
Whenever I create a new organization:
$organization = Organization::create($request->all());
Without a main_organization_id in my request, it fails with the following error:
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or
update a child row: a foreign key constraint fails
(myDB.organizations, CONSTRAINT
organizations_main_organization_id_foreign FOREIGN KEY
(main_organization_id) REFERENCES organizations (id)) (SQL:
insert into organizations (main_organization_id) values
())
But why does this fail? The field is nullable, does that mean I have to implicitly set main_organization_id to null in the request?
My $fillable:
protected $fillable = [
'main_organization_id',
];
My migration:
Schema::table('organizations', function (Blueprint $table) {
$table->integer('main_organization_id')->unsigned()->nullable();
$table->foreign('main_organization_id')->references('id')->on('organizations');
});**strong text**
I want to prevent code like this: $request['main_organization_id'] = null; before creating my new row. Is this possible?
Thank you for reading.
Yes, you should specify the field value while creating an Organization, you should do it like this:
$organization = Organization::create(array_merge([
'main_organization_id' => null,
], request()->all()));
Hope this helps!

Spring jpa column defaultvalue

I'm trying to do the following
#ManyToOne
#JoinColumn(name="tier_id", columnDefinition = "INT default 1", nullable = false)
public Tier getTier() {
return tier;
}
but while inserting the record I get
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'tier_id' cannot be null
I want default tier_id to be 1 if it's not set, but it's not working. How can I correctly set this up?
The default SQL value is only used if the column is not present at all in the insert statement.
But Hibernate doesn't omit columns in insert statements. If you create an entity instance with a null tier, and persist it, you're effectively saying Hibernate that you want to persist an entity with a null tier, and Hibernate explicitely sets the tier_id column to null, since that's what you told it to do.
So, if you want your entity's tier to be the tier with ID 1, then do it explicitely in your application code:
SomeEntity e = new SomeEntity();
e.setTier(em.getReference(Tier.class, 1));
em.persist(e);

Resources