Silex Doctrine "The EntityManager is closed" after Doctrine Exception - exception

I am registering Doctrine in Silex in this way:
// Doctrine
$this->register(new DoctrineServiceProvider(), array(
'db.options' => $this['config']['doctrine']['db.options']
));
$this->register(new DoctrineOrmServiceProvider());
$this['orm.em.options'] = $this['config']['doctrine']['orm.em.options'];
If I insert a duplicated row then I get this exception:
Integrity constraint violation: 1062 Duplicate entry
I have catched this exception using try/catch. If later I try to use again Doctrine, now always this exception is shown:
The EntityManager is closed.
If I try reload the EntityManager following these steps (The EntityManager is closed) :
if (!$app['orm.em']->isOpen()) {
$app['orm.em'] = $app['orm.em']->create(
$app['orm.em']->getConnection(), $app['orm.em']->getConfiguration(), $app['orm.em']->getEventManager()
);
}
But now this exception is shown:
Cannot override frozen service "orm.em"
How can I use Doctrine provider in Silex after a Doctrine exception is happened?
Thanks.

It is possible to remove from frozen state. And then create new EntityManager.
$manager = $app['orm.em'];
$app->offsetUnset('orm.em');
$app->offsetSet('orm.em', $manager->create($manager->getConnection(), $manager->getConfiguration()));

Related

Eloquent model cannot select from MySQL view

Has MySQL view 'histstat'.
In MySQL select * from histstat works fine.
Laravel model is very simple:
class HistStat extends Model
{
use HasFactory;
protected $table = 'histstat';
protected $fillable = ['day', 'total', 'paid'];
}
Then I want to get first 14 records of hisstat:
$dynamic = HistStat::all()->slice(14);
... and execution ends with error SQLSTATE[42000]: Syntax error or access violation: 1055 (SQL: select * from 'histstat')
When I try to use table-based model ($dynamic = History::all()->slice(14);) - everything works fine.
So, the problem in MySQL view + Laravel.
How to use view-based model in Laravel ?
For the SQL error,
In config\database.php in "mysql" array
Set 'strict' => false
I think this one will help Laravel: Syntax error or access violation: 1055 Error.
For the first 14 records, you can do it
HistStat::oldest()->take(14)->get();
better than all() because I do not recommend using it if you have a huge table that will be load on the server because all() get all records select * from "users"
In config/datatable.php (mysql section):
Change strict to false
Add / change in options - PDO::ATTR_EMULATE_PREPARES => true

Base table or view not found: 1146 Table doesn't exist

I have very strange situation.
The following code is working on my localhost, but on my server it is not working.
I got the error "Base table or view not found: 1146 Table 'beteu.bets' doesn't exist". The Model is looking not in the right database, that's why it cannot find the table. But he is not supposed to look in that database.
In the function, where I am calling the method i have made following test to check what is the active database:
DB::connection()->getPdo();
if(DB::connection()->getDatabaseName()){
echo "Yes! Successfully connected to the DB: " . DB::connection()->getDatabaseName();
}
die();
So here as a result I got the correct database "soccerbets", but than I try to output all results in the "bets" table like that:
DB::connection()->getPdo();
if(DB::connection()->getDatabaseName()){
echo "Yes! Successfully connected to the DB: " . DB::connection()->getDatabaseName();
print_r(Bet::get());
}
die();
And here I got again the strange error:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'beteu.bets' doesn't exist
Here is the code of the Bet model:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Bet extends Model {
protected $fillable = [
'ip', 'site',
];
}
I have tried also to define explicit the database in that Model, but nothing happens.
Please help me find that stupid error :)
The variable you are looking for in your model is
protected $connection = "connection of your second db name";
You also have to define a new connection (database) in your /config/database.php
If you don't want to expose your credentials in versioning, you also have to add at least one new .env variable to set the connection.
So similar to your default "mysql" connection, you can add a new connection, you can set the default connection in your .env

CakePHP SQL Error when trying to use loadModel

I have two controllers (Feeds & Items), on the Items add view, I want some information from the Feeds table visible to the user.
So in the Items Controller I'm trying to access the Feed model, everything I have come across recommends to use loadModel but when I try to load the Items add view, I getting the following error:
Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
SQL Query: SHOW TABLES FROM
Please note there is no relationship setup between these two tables.
Feed Model
App::uses('AppModel', 'Model');
class Feed extends AppModel {}
Item Model
App::uses('AppModel', 'Model');
class Item extends AppModel {}
Item Controller
App::uses('Feed','Model');
class ItemsController extends DirectResponseAppController {
function add() {
if ($this->request->is('post')) {
$this->Item->create();
if ($this->Item->save($this->request->data)) {
$this->Session->setFlash(__('Your item has been saved.'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Unable to add your item.'));
} else {
$this->loadModel('Feed');
$xxx = $this->Feed->find('all');
}
}
}
Any help appreciated.
** EDIT **
After a bit more digging, the problem seems to be with this line:
$xxx = $this->Feed->find('all');
I'm just not sure why.
If your Feed is inside a plugin (DirectResponse), you must use loadModel like this:
$this->loadModel('DirectResponse.Feed');

How to show MySQL errors from a failed Modx/xPDO query object?

How do I show the error mysql throws when I try to insert data into a custom table and the insert fails?
For example, below a bit of code that should(will) fail with an SQL error.
$insert = "some insert sql statement that will fail";
$myquery = $modx->query($insert);
if(!$myquery){
echo 'error occurred! <br>';
}
How do I return what the error actually was [i.e. column mismatch, unique id exists etc.]?
There is a little bit easier way to track your custom xpdo request.
$c = $modx->newQuery('modResource');
$c->where(array(
'id1' => 1
));
// print request for control
print_r($c->toSQL());
$s = $c->prepare();
$s->execute();
print_r($s->errorInfo());
After execution we can catch an error:
Array ( [0] => 42S22 [1] => 1054 [2] => Unknown column 'modResource.id1' in 'where clause' )
It's all because xpdo use pdo and controls execution with it's help. Some code from xpdo source:
/**
* #see http://php.net/manual/en/function.pdo-errorinfo.php
*/
public function errorInfo() {
if (!$this->connect()) {
return false;
}
return $this->pdo->errorInfo();
}
Based on the examples in the xPDO Getting Started guide, $modx in this context appears to be a class extending PDO and the result resource object $myquery is likely a PDOStatement object.
You can therefore set an exception error mode on $modx as you would with a normal PDO object.
$modx->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
to force it to throw errors on failure. By default, PDO errors silently; its error modes are documented here.
Correction: Looking into the xPDO source it does not extend PDO, but rather contains a PDO object as a property and implement PDO methods, passing them through to its connection property. So the setAttribute() call will be passed through to the underlying PDO object and should work accordingly.
The xPDO constructor extends functionality from a normal PDO constructor slightly, and accepts an array of options in the 5th parameter where you may set the error mode, rather than setting it later via setAttribute():
$xpdo = new xPDO($dsn, $user, $password, [], [PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION]);
Whichever method you choose to set it, you may wrap your code in a try/catch block to catch exceptions of type PDOException on error:
try {
$insert = "some insert sql statement that will fail";
$myquery = $modx->query($insert);
}
catch (PDOException $e) {
echo 'error occurred! ' . $e->getMessage() . '<br>';
}
You may also more simply set the errormode to PDO::ERRMODE_WARNING and PHP will instead just emit E_WARNING messages, which unlike exceptions, are non-fatal.
I was able to verify all of this works as expected by setting up a quick test with xPDO.

Transaction with many deletes followed by many inserts with Hibernate and Spring

I use spring boot + MySQL5 database.
There is a periodic service that runs and need to do the following transaction:
Delete records (with condition)
Insert records
In addition another service does select queries and should see a snapshot of the records without interfering with the delete+insert transactions.
I have the following code:
#Service
public class BulkInsert
{
public static final String DELETE_ALL_ROWS_QUERY = "DELETE FROM GnsEntity where is_synced = true and was_removed = false";
#Inject
private EntityManager entityManager;
#Transactional
public void save(List<GnsEntity> gnsEntityList)
{
Session session = entityManager.unwrap(Session.class);
Query entity = session.createQuery(DELETE_ALL_ROWS_QUERY);
entity.executeUpdate();
for (int i = 0; i < gnsEntityList.size(); ++i)
{
try
{
session.persist(gnsEntityList.get(i));
}
catch(NonUniqueObjectException nonUniEx)
{
}
}
}
}
In general it seems to work good.. though a lot of times there's a deadlock exception and I have no clue why..
Thats why I was wondering if my code is relatively fine?
I get the following errors every now and then:
DEBUG","message":"Creating new transaction with name
[com.ddd.swiss.microservices.gnssynchronizer.BulkInsert.save]:
PROPAGATION_REQUIRED,ISOLATION_DEFAULT","service":"GNSSynchronizer","instanceId":"1","application":"Start","space":"ngampel","class":"org.springframework.orm.jpa.JpaTransactionManager","thread":"pool-3-thread-1","X-B3-TraceId":"5db000bfb3de1a6d49a53edd707419a0","X-B3-SpanId":"49a53edd707419a0"}
{"#timestamp":"2019-10-23T07:27:24.318Z","logLevel":"DEBUG","message":"Opened
new EntityManager
[org.hibernate.jpa.internal.EntityManagerImpl#5a445da1] for JPA
transaction","service":"GNSSynchronizer","instanceId":"1","application":"Start","space":"ngampel","class":"org.springframework.orm.jpa.JpaTransactionManager","thread":"pool-3-thread-1","X-B3-TraceId":"5db000bfb3de1a6d49a53edd707419a0","X-B3-SpanId":"49a53edd707419a0"}
{"#timestamp":"2019-10-23T07:27:24.318Z","logLevel":"DEBUG","message":"begin","service":"GNSSynchronizer","instanceId":"1","application":"Start","space":"ngampel","class":"org.hibernate.engine.transaction.internal.TransactionImpl","thread":"pool-3-thread-1","X-B3-TraceId":"5db000bfb3de1a6d49a53edd707419a0","X-B3-SpanId":"49a53edd707419a0"}
{"#timestamp":"2019-10-23T07:27:24.319Z","logLevel":"DEBUG","message":"Exposing
JPA transaction as JDBC transaction
[org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle#241c36b8]","service":"GNSSynchronizer","instanceId":"1","application":"Start","space":"ngampel","class":"org.springframework.orm.jpa.JpaTransactionManager","thread":"pool-3-thread-1","X-B3-TraceId":"5db000bfb3de1a6d49a53edd707419a0","X-B3-SpanId":"49a53edd707419a0"}
{"#timestamp":"2019-10-23T07:27:24.319Z","logLevel":"DEBUG","message":"delete
from gns_entity where is_synced=1 and
was_removed=0","service":"GNSSynchronizer","instanceId":"1","application":"Start","space":"ngampel","class":"org.hibernate.SQL","thread":"pool-3-thread-1","X-B3-TraceId":"5db000bfb3de1a6d49a53edd707419a0","X-B3-SpanId":"49a53edd707419a0"}
{"#timestamp":"2019-10-23T07:27:25.451Z","logLevel":"DEBUG","message":"could
not execute statement
[n/a]","stackTrace":"com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:
Deadlock found when trying to get lock; try restarting
transaction\n\tat
sun.reflect.NativeConstructorAccessorImpl.newInstance0(Nativ
Thanks for the help!