Symfony 整合 GatewayWorker 碰到的问题

Error while sending QUERY packet 错误

MySQL 的 max_allowed_packet 太小, 在 [mysqld] 下修改 max_allowed_packet, 然后重启MYSQL

1
2
3
4
5
6
7
8
9
10
[mysqld]
max_allowed_packet=16M

mysql> SHOW VARIABLES LIKE 'max_allowed_packet';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| max_allowed_packet | 16777216 |
+--------------------+----------+
1 row in set

实际错误可能是 MySQL server has gone away, 设置 MySQL 的 wait_timeout = 10, 并且每次操作后, 主动关闭数据库连接
wait_timeout 配置
Symfony 中的处理方式, 每次获取 Repository 时, 都需验证 MySQL 连接状态, 若无法ping通, 则断开重连

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* Gets a named entity manager.
*
* @param string $name The entity manager name (null for the default one)
* @return \Doctrine\ORM\EntityManager
*/
public static function getEntityManager($name = null)
{
if (!isset(self::$em)) {
self::$em = self::getService('doctrine')->getManager($name);
}

if (!self::$em->isOpen()) {
$doctrine = self::getService('doctrine');
$doctrine->resetManager($name);
self::$em = $doctrine->getManager($name);
}

$conn = self::$em->getConnection();
if ($conn->ping() === false) {
$conn->close();
$conn->connect();
}

return self::$em;
}

若直接操作数据库进行了数据的修改, TCP 长连接中获取数据不是最新的

每次获取 Repository 时, 调用 clear() 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* Gets the EntityRepository for an entity.
*
* @param string $entityName The name of the entity.
* @param string $entityManagerName The entity manager name (null for the default one)
* @param bool $clear Clears the repository
* @return EntityRepository
*/
public static function getRepository($entityName, $entityManagerName = null, $clear = true)
{
$container = self::initContainer();
$em = self::getEntityManager($entityManagerName);
$entityName = self::COMMON_BUNDLE . ":{$entityName}";
$repository = $em->getRepository($entityName);
$repository->init($container);
$clear && $repository->clear();

return $repository;
}

OrderUser 配置了关联映射, 通过Order#User关系找到一个新实体, 该关系未配置为级联实体的持久操作

具体错误:A new entity was found through the relationship 'Bundles\CommonBundle\Entity\Order#User' that was not configured to cascade persist operations for entity: Bundles\CommonBundle\Entity\User@000000005db8782900000000730db886. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Bundles\CommonBundle\Entity\User#__toString()' to get a clue.
OrderUser

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// 第一种, 删除 `Order` 和 `User` 的关联配置

// 第二种:在查询前清除EntityManager
$em = self::getEntityManager();
$em->clear();

$orderRepository = self::getRepository('Order');
$order = $orderRepository->findOneBy(['orderNum' => '201711271543190607981']);

$userRepository = self::getRepository('User');
$user = $userRepository->findOneBy(['id' => 5]);

$orderRepository->saveOrder($order, [
'orderMoney' => '12',
]);

// 第三种:查询 User 后, 调用 clear()
$orderRepository = self::getRepository('Order');
$order = $orderRepository->findOneBy(['orderNum' => '201711271543190607981']);

$userRepository = self::getRepository('User');
$user = $userRepository->findOneBy(['id' => 5]);
$userRepository->clear();

$orderRepository->saveOrder($order, [
'orderMoney' => '12',
]);

// 第四种:在更新 Order 前, 刷新 $order 实体类, 这样 Symfony 就会重新去取得 $order 所映射的 User 实体类
$orderRepository = self::getRepository('Order');
$order = $orderRepository->findOneBy(['orderNum' => '201711271543190607981']);

$userRepository = self::getRepository('User');
$user = $userRepository->findOneBy(['id' => 5]);

$em->refresh($order);
$orderRepository->saveOrder($order, [
'orderMoney' => '12',
]);

// 第五种:调整执行顺序
$orderRepository = self::getRepository('Order');
$order = $orderRepository->findOneBy(['orderNum' => '201711271543190607981']);

$orderRepository->saveOrder($order, [
'orderMoney' => '12',
]);

$userRepository = self::getRepository('User');
$user = $userRepository->findOneBy(['id' => 5]);

开启事务后, 偶尔会提示 There is no active transaction.

EntityManager 重复定义所导致, 使用单例模式
当初碰到这个错误的时是因为开启事务的时候, 实例化了 EntityManager, 当获取持久类时, getRepository 时又实例化了 EntityManager, 这是两个不同的 EntityManager, 所以偶尔会出现以上错误

开启事务后, 偶尔会提示 The entityManager is closed.

每次事务处理完后都关闭 EntityManager, 当收到新请求, 重新调用 EntityManager 时, 没有判断是否被关闭, EntityManager 获取方法

1
2
3
4
5
6
7
8
9
10
11
12
/**
* rollback and close transaction.
*/
public static function closeTransaction()
{
if (isset(self::$em)) {
if (self::$em->getConnection()->isTransactionActive()) {
self::$em->close();
self::$em->rollback();
}
}
}
0%