I have three entities in my project.
First Entity:
class Entity1
{
/**
* #ORM\ManyToMany(targetEntity="App\MyBundle\Entity\Entity2", inversedBy="i")
*
*/
protected $j;
}
Second Entity:
class Entity2
{
/**
* #ORM\ManyToMany(targetEntity="App\MyBundle\Entity\Entity1", mappedBy="j")
*/
protected $i;
}
Now i have a manyToMany connection between entity 1 and entity 2, the table look like this.
Tablename: entity1_entity2
Fields: entity1_id, entity2_id
I would like to create a third entity and connect this to the related table entity1_entity2 with a oneToMany relation? How can i do this? Is this use case possible?
Related
I'm using EF Core 6 on a project. Most of my tables have a field like CreatedBy/UpdatedBy that includes a user id. There are only a few occasions where I need to show the full name associated with the user id, but that value is in another table in a different database, but on the same server.
Is creating a view that joins to the needed table only way to handle this? Could I create function in the database where my EF Core entities are modeled? How would that work code wise?
As EF context does not support cross database queries. Therefore, workaround can be a SQL view.
Is creating a view that joins to the needed table only way to handle this?
Yes you can do that. While creating view you should consider below way:
SELECT {Your 1st Table Column} [YourFirstDatabase].[dbo].[Your1stDbTable] WHERE UserId = (SELECT {Your 2nd Table Column} FROM [YourSecondDatabase].[dbo].[Your2ndDbTable] WHERE Category = 'Cat')
Could I create function in the database where my EF Core entities are modeled?
You could create function, stored procedure and view to achieve that. Afterwards, you should define that within a POCO Class finally call that on your context. For instance, here I am showing the example using a SQL view:
SQL view:
USE [DatabaseName_Where_You_Want_to_Create_View]
CREATE VIEW [ExecuteQueryFromOneDbToAnother]
AS
SELECT UserId, UserType,CreatedDate
FROM [RentalDb].[dbo].[Users]
WHERE UserId = (SELECT AnimalId
FROM [PetAnalyticsDb].[dbo].[Animal]
WHERE Category = 'Cat')
Note: I am simulating the example where I have two database from that I have two table where these columns, I would use in first database table UserId, UserType, CreatedDate and in second database from Animal table from the AnimalId I will search the user
How would that work code wise?
Following example would guided you how the implementation in the code should be.
Database context:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext (DbContextOptions<ApplicationDbContext > options) : base(options)
{
}
public DbSet<MultipleDBQueryExecutionModel> multipleDBQueryExecutionModels { get; set; }
override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MultipleDBQueryExecutionModel>().ToTable("ExecuteQueryFromOneDbToAnother");
}
}
Note: put your view name while map in DbContext to table ToTable("ExecuteQueryFromOneDbToAnother");. Here ExecuteQueryFromOneDbToAnother is the view name.
POCO class:
public class MultipleDBQueryExecutionModel
{
[Key]
public Int UserId { get; set; }
public string UserType { get; set; }
public DateTime CreatedDate { get; set; }
}
Controller:
[HttpGet]
public ActionResult GetDataFromDifferentDatabase()
{
var data = _context.multipleDBQueryExecutionModels.ToList();
return Ok(data);
}
Output:
As our project scaled we decided that every single data should belong to companies that created them. Therefore I'm to add a column "data_owner_company_id" that points to the company that owns given record. Yes it's possible to generate migration to add this column to each model but that is not really feasible since there is 120+ tables & models. How can i tackle this with minimum effort ?
For the model part i figured i can easily apply it to all models by inheritance, but not sure about migration.
TL;DR
How to add int column to all tables by migration ?
Database: MySQL v8
Framework: Laravel 8, PHP 7.3
It's simple if you find all the tables' names in your database, you have to loop and create columns for each and every table.
Try creating columns using queues as it will be a heavy job for 120 tables.
Check the following code:
class CreateDataOwnerCompanyIdtoEachTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up ()
{
$columns = 'Tables_in_' . env('DB_DATABASE');//This is just to read the object by its key, DB_DATABASE is database name.
$tables = DB::select('SHOW TABLES');
foreach ( $tables as $table ) {
//todo add it to laravel jobs, process it will queue as it will take time.
Schema::table($table->$columns, function (Blueprint $table) {
$table->unsignedInteger('data_owner_company_id');
});
}
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down ()
{
$columns = 'Tables_in_' . env('DB_DATABASE');//This is just to read the object by its key, DB_DATABASE is database name.
$tables = DB::select('SHOW TABLES');
foreach ( $tables as $table ) {
//todo add it to laravel jobs, process it will queue as it will take time.
Schema::table($table->$columns, function (Blueprint $table) {
$table->dropColumn('data_owner_company_id');
});
}
}
}
I'm not 100% sure that it's going to work, but here it goes:
Create class that extends Illuminate\Database\Schema\Blueprint;
In constructor call parent construntor and then
$this->unsignedBigInteger('data_owner_company_id')->nullable();
Use your new class in migrations instead of default Blueprint
How to run SQL query in spring boot when my tables' name is dynamic and the number of the columns of the table is also dynamic/varying depending on the requirement.
While using entity class we require to set static table and column names.
Eg-
Table- FunndTransfer_Category1 have columns - id,name,amount,abc
Table- FunndTransfer_Category2 have columns - id,name,amount,xyz
here column name abc,xyz will add at time of table creation when user upload it.
Is there any alternate approach to run query??
you can use something as below
#PersistenceContext
private EntityManager entityManager;
List<Object> getData(){
String tableName = "FunndTransfer_Category1";
Query query = entityManager.createNativeQuery("select * from "+tableName);
return query.getResultList();
}
I tried cascade remove on the 'file' entity that keeps my 'expanse' entity from removing. But this doesn't work.
The error:
Cannot delete or update a parent row: a foreign key constraint fails (zioo.files, CONSTRAINT FK_6354059F395DB7B FOREIGN KEY (expense_id) REFERENCES expenses (id))
The file entity code:
/**
* #ORM\ManyToOne(targetEntity="Expense", inversedBy="files", cascade={"remove"})
* #ORM\JoinColumn(name="expense_id", referencedColumnName="id")
*/
private $expense;
The expanse entity code:
/**
* #ORM\OneToOne(targetEntity="File", cascade={"persist"})
* #ORM\JoinColumn(name="file_id", referencedColumnName="id")
*/
private $file = null;
/**
* #ORM\OneToMany(targetEntity="File", mappedBy="expense", cascade={"remove"})
*/
protected $files;
If a expanse gets deleted the file associated with it should be deleted too.
Using cascade={"remove"} the entity won't be deleted if it is owned by something else. The issue seems to be caused by doctrine, as the expanse entity has 2 relations to file entity and this causes doctrine to "think" that your file entity is owned by something else and not send a delete to database for it, before trying to delete the expanse.
As a result when it tries to delete the expanse this error is thrown.
To test it, remove private $file = null;relation and will see that it will work.
To overcome this, I suggest to use onDelete="CASCADE" on the owning side:
/**
* #ORM\ManyToOne(targetEntity="Expense", inversedBy="files", cascade={"remove"})
* #ORM\JoinColumn(name="expense_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $expense;
In this case, you no longer need cascade={"remove"}:
/**
* #ORM\OneToMany(targetEntity="File", mappedBy="expense")
*/
protected $files;
Doctrine delete relation options
I am trying to get a many-to-many relationship working using Grails 2.0.1 on Windows 7. I have exhausted both Google, this site, and my Grails books. Nothing worked. I am connecting to a MS SQL Server 2005 database that I have READ only privileges on and yes - it is a legacy database. Everything in the 2 individual tables works fine (views OK & all) but when I try to add the join table code I get an error:
org.hibernate.HibernateException: Missing table: dbo.IN_USR_DRAWING_PRIV
The table does indeed exist and I can see it fine using IntelliJ's IDEA 10.5 Data Sources view & the MS SQL Server Management Studio. The relevant part of the error is this (I can send more ... much more if needed) :
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.HibernateException: Missing table: dbo.IN_USR_DRAWING_PRIV
Here are the 2 domain classes :
class Drawing {
static hasMany = [appusers:Appuser]
String id
String drawingId //this is in the join table
String drawingName
static transients = ['name']
void setName(String name) {
id = name
}
String getName() {
return id
}
static mapping = {
table name: "IN_DRAWING", schema: "dbo"
version false
id column: 'DRAWING_ID', generator:'identity', insertable:false, updateable:false
drawingId column: "`DRAWING_ID`",insertable:false, updateable:false //this is in the join table
drawingName column: "`DRAWING_NAME`"
appusers column: '`USR_ID`',
joinTable: 'IN_USR_DRAWING_PRIV'
}
}
class Appuser {
static belongsTo = Drawing
static hasMany = [drawings:Drawing]
String id
String usrId //this is in the join table
String usrName
static transients = ['name']
void setName(String name) {
id = name
}
String getName() {
return id
}
static mapping = {
table name: 'IN_USR', schema: "dbo"
version false
id column:'USR_ID', generator:'identity', insertable:false, updateable:false //this is in the join table
drawings column: 'DRAWING_ID',
joinTable: 'IN_USR_DRAWING_PRIV'
usrName column: "`USR_NAME`"
}
}
And here is the schema for the join table:
dbo.IN_USR_DRAWER_PRIV
USR_ID (PK, varchar(23), not null)
DRAWING_ID (PK, FK, varchar(23), not null)
PRIV_ID (PK, int, not null)
GRAG reports it has a composite key of all 3 columns, which it does along with a FK on DRAWING_ID.
Solutions that I have tried :
This code (which fails with the "Missing Table" exception.
Adding a domain controller for the join table - same result.
Any hints/clues/solutions appreciated.
I fixed this by using Groovy SQL directly and passing in the T-SQL.