Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.Tue Oct 10 17:11:14 IST 2018 There was an unexpected error (type=Internal Server Error, status=500). could not execute statement; SQL [n/a]; nested exception is org.
hibernate.exception.SQLGrammarException: could not execute statement.
STS Error:
Before changing the code
com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolation
Exception
: Cannot add or update a child row: a foreign key constraint fails
(workdemo.officeinfo, CONSTRAINT idFOREIGN KEY (id) REFERENCES mytable
(id))
After implementing joincolumn
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'entityManagerFactory' defined in class path
resource [org/springframework/boot/autoconfigure/orm/jpa/
HibernateJpaConfiguration.class]: Invocation of init method failed;
nested exception is org.hibernate.AnnotationException: No identifier
specified for entity:com.infidata.modal.MyTable
POJO( value with getters and setters,also
generated value)
Office.java
package com.infidata.modal;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
#Entity
#Table(name="officeinfo")
public class Office {
#Id
private int sno;
private String batchno;
#ManyToOne
#JoinColumn(name = "id" )
private MyTable myTable;
private String fees;
private String reciptno;
private String trainer;
public Office() {
}
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
public String getBatchno() {
return batchno;
}
public void setBatchno(String batchno) {
this.batchno = batchno;
}
public String getFees() {
return fees;
}
public void setFees(String fees) {
this.fees = fees;
}
public String getReciptno() {
return reciptno;
}
public void setReciptno(String reciptno) {
this.reciptno = reciptno;
}
public String getTrainer() {
return trainer;
}
public void setTrainer(String trainer) {
this.trainer = trainer;
}
public Office(String batchno,String fees, String reciptno,String trainer) {
super();
this.batchno = batchno;
this.fees = fees;
this.reciptno = reciptno;
this.trainer=trainer;
}
#Override
public String toString() {
return "Office [sno=" + sno + ", batchno=" + batchno + ",fees=" + fees
+ ", reciptno=" + reciptno + ",trainer=" + trainer + "]";
}
}
MyTable.java
package com.infidata.modal;
#Entity
public class MyTable {
}
Database(name of database is workdemo)
User table(Table name: mytable)
CREATE TABLE `mytable`
( `id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
`mobile` varchar(10) NOT NULL,
`email` varchar(45) NOT NULL,
`college` varchar(45) NOT NULL,
`branch` varchar(45) NOT NULL,
`semester` varchar(45) NOT NULL,
`address` varchar(105) NOT NULL,
`internship` varchar(45) NOT NULL,
`batch` varchar(45) NOT NULL,
`startdate` varchar(45) NOT NULL,
`enddate` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci
Office table(Table name:office)
CREATE TABLE `office`
(`sno` int(11) NOT NULL AUTO_INCREMENT,
`batchno` varchar(45) NOT NULL,
`id` int(11) NOT NULL,
`fees` varchar(45) NOT NULL,
`reciptno` varchar(45) NOT NULL,
PRIMARY KEY (`sno`),
KEY `id_idx` (`id`),
CONSTRAINT `id` FOREIGN KEY (`id`) REFERENCES `mytable` (`id`)
)
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
The id(foreign key) in office table should be autoincremented with reference to student id column attribute
The problem is how you defined the entity class :
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
When you use JPA, you must specify the target entity of the relationship, not the field from database.
Your definition just tells the hibernate to generate an int value which will not correspond to a real entity.
It should be something like this:
#ManyToOne
#JoinColumn(name = "id" )
private User user;
Your office object will be
#Entity
#Table(name = "officeinfo")
public class Office {
#Id
private int sno;
private String batchno;
#ManyToOne
#JoinColumn(name = "id")
private User user;
private String fees;
private String reciptno;
private String trainer;
// getters and setters;
}
Please make sure that #Id is only on sno and you don't have on another fields, otherwise it will fail with composite key exception. Please remove id from your object, it is the foreign key to User and it is handled by:
#ManyToOne
#JoinColumn(name = "id")
private User user;
My tables (Mysql DB):
// Stores Table
CREATE TABLE IF NOT EXISTS `app_beta`.`stores` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`))
// Items Table
CREATE TABLE IF NOT EXISTS `app_beta`.`items` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT UNSIGNED NOT NULL,
`title` TEXT NOT NULL,
`content` LONGTEXT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_items_user_id`
FOREIGN KEY (`user_id`)
REFERENCES `app_beta`.`users` (`id`))
// Products Table
CREATE TABLE IF NOT EXISTS `app_beta`.`products` (
`id` INT UNSIGNED NOT NULL,
`reviews` DECIMAL(7,1) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_products_id`
FOREIGN KEY (`id`)
REFERENCES `app_beta`.`items` (`id`))
// Product_Store Table
CREATE TABLE IF NOT EXISTS `app_beta`.`products_stores` (
`product_id` INT UNSIGNED NOT NULL,
`store_id` INT UNSIGNED NOT NULL,
`price` DECIMAL(7,2) NOT NULL,
`url` VARCHAR(255) NOT NULL,
CONSTRAINT `fk_products_store_product_id`
FOREIGN KEY (`product_id`)
REFERENCES `app_beta`.`products` (`id`),
CONSTRAINT `fk_products_stores_store_id`
FOREIGN KEY (`store_id`)
REFERENCES `app_beta`.`stores` (`id`))
// Offers Table
CREATE TABLE IF NOT EXISTS `app_beta`.`offers` (
`id` INT UNSIGNED NOT NULL,
`store_id` INT UNSIGNED NOT NULL,
`price` DECIMAL(7,2) NULL,
`url` VARCHAR(255) NOT NULL,
`start_date` DATE NOT NULL,
`end_date` DATE NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_offers_store_id`
FOREIGN KEY (`store_id`)
REFERENCES `app_beta`.`stores` (`id`),
CONSTRAINT `fk_offers_id`
FOREIGN KEY (`id`)
REFERENCES `app_beta`.`items` (`id`))
Add. Info:
My tables are migrated. Just to clarify... the products and offers inherit from the items table. If the item is not created I can not add products and offers.
The product can have the title, summary, content, category etc... same for the offer.
The product can be on 1-many stores
The offer can be only on 1-1 store.
If I'm wrong LET ME KNOW!
** Please, I want someone to help me creating the relationships between the Item model, product and offer. Can i use polymorphic relations? **
Models DONE:
class Store extends Model
{
public function offers()
{
return $this->hasMany('App\Offer');
}
public function products()
{
return $this->hasMany('App\Product');
}
}
class Product extends Model
{
public function stores()
{
return $this->belongsToMany('App\Store');
}
}
class Offer extends Model
{
public function store()
{
return $this->belongsTo('App\Offer');
}
}
using php artisan tinker, all works nice!
namespace App
$user = new User
$store = new Store
$item = new Item
$item->id = 1
$item->user_id = 1
$item->title = 'test'
$item->content 'test'
$item->save();
true
$item2 = new Item
$item2->id = 2
....
true
$product1 = new Product
$product1->id = 1 (FK item->id)
$product1->reviews = 5
$product1->save()
true
$offer1 = new Offer
$offer1->id = 2 (FK item->id)
$offer1->store_id = 1
...
true
I'll add later a function to attach product to one or many stores (products_stores table).
Thanks.
This is how I think you can have a good start...
First of all, your model and migration can handle all it.
There is for relationship:Laravel 5.2 Relationship
There is for migration:Laravel 5.2 Migration
So there you create your migration:
Schema::create('stores', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->string('name', 50);
$table->timestamps();
});
Schema::create('items', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->bigInteger('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->text('title');
$table->longText('content');
$table->timestamps();
});
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('store_id')->unsigned();
$table->foreign('store_id')->references('id')->on('stores');
$table->decimal('reviews', 7,1);
$table->timestamps();
});
Schema::create('offers', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('store_id')->unsigned();
$table->foreign('store_id')->references('id')->on('stores');
$table->bigInteger('item_id')->unsigned();
$table->foreign('item_id')->references('id')->on('items');
$table->decimal('price', 7,2);
$table->string('url', 255);
$table->dte('start_date');
$table->dte('end_date');
$table->timestamps();
});
So, once you did this, you can make your relationship onto your model. This way you don't need all the "between" tables. When you will use associate(), Laravel will create the link for you. This way you can do something like this: $offer->store()->name to get the name of the store of the current offer. Take a look:
Into Store's model
public function products()
{
return $this->hasMany(Product::class);
}
public function offers()
{
return $this->hasMany(Offer::class);
}
Into Offer's model
public function store()
{
return $this->belongsTo(Store::class);
}
This way, You create a one-to-many relation. Has I said, $offer->store() will retrieve the store of the offer. $store->offers()->get() will retrieve all offer of the store.
Hope it help.
EDIT
There is one only problem with what I said. The n + 1 problem. So like it explain there(search google "laravel n+1 problem" and pick the link to laracast) (can't put it as a link, not enough reputation) , when you call things like I said, the script will do 2 query. When you use a foreach() loop, it'll have as much loop +1 query. I suggest you to do things like that
$offers = Offer::with('store')->all();
This way you'ill have only 1 query and you will still able to do
$offer->store;
without doing another query.
When you use $model = Model::with('something')->all();, the query will fetch data from 2 table and return the result with an array into an array. Like this:
offers {
[0]:{a,b,c,d,e, store{a,b,c,d,e}}
[1]:{a,b,c,d,e, store{a,b,c,d,e}}
[2]:{a,b,c,d,e, store{a,b,c,d,e}}
[3]:{a,b,c,d,e, store{a,b,c,d,e}}
}
You can use the opposite:
$stores = Store::with('offers')->all();
So you can use:
$store->offers[i]->somthing;
Because the array will look like this:
stores {
[0]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
[1]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
[2]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
}
I have a couple of tables in my database:
CREATE TABLE IF NOT EXISTS `team_players` (
`artificialid` int(11) NOT NULL AUTO_INCREMENT,
`team_name_id` int(11) NOT NULL,
`player_id` int(11) NOT NULL,
PRIMARY KEY (`artificialid`)
)
And:
CREATE TABLE IF NOT EXISTS `team_names` (
`id` int(11) NOT NULL,
`name` varchar(50) NOT NULL
)
And I have set up my TeamPlayer model like this:
class TeamPlayerModel extends AppModel {
public $belongsTo = array(
'TeamName',
'Player'
)
);
}
The players table has a field id, but neither of the associations are working.
I don't really understand why it isn't working, I have something like this working in another app, pretty much line for line.
Thanks in advance, I really appreciate any help.
You can try to setup your model:
TeamPlayer.php:
class TeamPlayer extends AppModel {
public $hasMany = array(
'PlayerName'
)
) ;
}
TeamName.php:
class TeamName extends AppModel {
public $belognsTo = array(
'TeamPlayer'
)
) ;
}
Here's my database schema:
create table Personas
(
id int primary key AUTO_INCREMENT,
Nombre varchar(255),
Apellidos varchar(255),
FechaDeNacimiento date,
Sexo Bool,
CarnetDeIdentidad varchar(255)
);
create table Tutors
(
id int primary key AUTO_INCREMENT,
persona_id int,
FOREIGN KEY (persona_id) REFERENCES Personas(id)
);
create table Alumnos
(
id int primary key AUTO_INCREMENT,
persona_id int,
FOREIGN KEY (persona_id) REFERENCES Personas(id)
);
create table CoordinadorDeProgramas
(
id int primary key AUTO_INCREMENT,
persona_id int,
FOREIGN KEY (persona_id) REFERENCES Personas(id)
);
And here are my Model declarations:
<?php
class Alumno extends AppModel {
public $belongsTo = 'Persona';
}
<?php
class Coordinadordeprograma extends AppModel {
public $belongsTo = 'Persona';
}
<?php
class Tutor extends AppModel {
public $belongsTo = 'Persona';
}
<?php
class Persona extends AppModel {
public $hasOne = array('Alumno', 'Tutor', 'Coordinadordeprograma');
}
In my Controller I just want to fetch all Persona records if they have a foreign key relationship in Alumnos (for example).
Here's my code, I hope it illustrates what I'm trying to do:
public function filter($type = null) {
if ($type == "alumno") { // www.app.com/personas/filter/alumno
$this->set('personas', $this->Alumno->Persona->find('all'));
}
}
However this is returning every single Persona record, and not just the ones that have a record in the Alumno table.
How do you suggest I solve this problem? I thought that by using $this->Alumno->Persona I would only be reaching for Persona's that are in the Alumno table.
Thanks!
You could use the containable behaviour and just make a find on Alumno??
$this->set('personas', $this->Alumno->find('all'));
it should retrieve the 'Alumno' with all the models associated to it. You could also choose which models you want to retrieve. For example, this code will retrieve all the 'Alumno' with its corresponding 'Persona'
$this->set('personas', $this->Alumno->find('all',array('contain'=>array('Persona')));
An of course.. like #Paulo answered, you could manually make the join, but using "containable" is cleaner. I only make the join manually when I don't have any other solution.
Hope this helps,
You can try make INNER JOIN on the fly, like this:
$personas = $this->Alumno->Persona->find('all', array(
'joins' => array(
array(
'table' => 'Alumnos',
'alias' => 'Alumno',
'type' => 'INNER',
'conditions' => 'Persona.id = Alumno.persona_id'
)
)
));
$this->set('personas', $personas);
I am having problems performing a cascade persist operation on a parent entity. When the child entity is persisted, the reference (generated id) to the parent entity is null. How would I get this to persist correctly?
Entities:
#Entity
public class Contact {
#Id #GeneratedValue(strategy=GenerationType.TABLE, generator="contact_gen")
#TableGenerator(name="contact_gen",
table="id_gen", pkColumnName="gen_name",
valueColumnName="gen_val", pkColumnValue="cont_gen")
#Column(name="contact_id")
private Long id;
#Column(name="name")
private String name;
#OneToMany(mappedBy="contact", cascade=CascadeType.PERSIST)
private List<Address> addresses = new ArrayList<Address>();
public void addAddress(Address address) {
addresses.add(address);
}
...
}
#Entity
public class Address {
#Id #GeneratedValue(strategy=GenerationType.TABLE, generator="address_gen")
#TableGenerator(name="address_gen",
table="id_gen", pkColumnName="gen_name",
valueColumnName="gen_val", pkColumnValue="addr_gen")
#Column(name="address_id")
private Long id;
#Column(name="full_address")
private String fullAddress;
#ManyToOne
#JoinColumn(name="contact_id")
private Contact contact;
...
}
Service:
#Stateless
public class ContactService {
#PersistenceContext
private EntityManager em;
public void createContact() {
Contact contact = new Contact();
contact.setName("Michael Scott");
contact.addAddress(new Address("1725 Slough Avenue");
em.persist(contact);
}
}
MySQL Tables & Inserts:
CREATE TABLE `contact` (
`contact_id` int(11) NOT NULL,
`name` varchar(45) NOT NULL
PRIMARY KEY (`contact_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `address` (
`address_id` int(11) NOT NULL,
`full_address` varchar(100) NOT NULL,
`contact_id` int(11) NOT NULL,
PRIMARY KEY (`address_id`),
KEY `FK_ADDRESS_contact_id` (`contact_id`),
CONSTRAINT `FK_ADDRESS_contact_id` FOREIGN KEY (`contact_id`) REFERENCES `contact` (`contact_id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE id_gen (
gen_name VARCHAR(80),
gen_val INT,
PRIMARY KEY (gen_name)
);
INSERT INTO id_gen (gen_name, gen_val) VALUES ('cont_gen', 0);
INSERT INTO id_gen (gen_name, gen_val) VALUES ('addr_gen', 0);
Sadly, you're not showing the content of addAddress. Since your association is bidirectional, are you setting "both sides of the link" in this method? Something like this:
#Entity
public class Contact {
...
#OneToMany(mappedBy="contact", cascade=CascadeType.PERSIST)
private List<Address> addresses = new ArrayList<Address>();
public void addToAddresses(Address address) {
address.setContact(this);
this.addresses.add(address);
}
}