SQL 表的顺序标识符的内在缺点是最终用户有可能轻松地遍历您的表。有时这是一个问题。
一个解决方案是创建一个非序列化的 id,每一行都不可猜测。
很明显,这个 id 必须是一个唯一的字段。我可以使用随机函数为每一行生成这些唯一 ID,但它有可能与先前设置的 ID 发生冲突。如果发生碰撞,最终用户会将其视为随机错误...
这里有一个解决这个问题的简单方法:
$keyValid = false;
while(!$keyValid) {
// Create a new random key
$newKey = generateKey();
// Check if the key already exists in database
$existingPotato = $em->getRepository('Potato')->findOneBy(array('key' => $newKey));
if (empty($existingPotato)) {
$keyValid = true;
}
}
// Hooray, key is unique!
每次我想要一个新 ID 时,它都会强制我至少执行一个 SELECT 语句。
那么,是否有更好的、被广泛接受的解决方案来解决这个问题?
或者,是否有优化的 id 长度,通过使冲突概率可以忽略不计(对于 3,000,000 行的表)使这个问题无关紧要?
最佳答案
您可以添加 Custom id generation strategy去做吧。您可以通过创建一个扩展 AbstractIdGenerator 的类来实现它:
use Doctrine\ORM\Id\AbstractIdGenerator;
class NonSequencedIdGenerator extends AbstractIdGenerator
{
public function generate(\Doctrine\ORM\EntityManager $em, $entity)
{
$class = $em->getClassMetadata(get_class($entity));
$entityName = $class->getName();
do {
// You can use uniqid(), http://php.net/manual/en/function.uniqid.php
$id = generateKey();
} while($em->find($entityName, $id));
return $id;
}
}
然后在您的实体类中使用注解添加它:
/**
* @ORM\Id
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class="NonSequencedIdGenerator")
*/
private $id;
但是如果您的 generateKey
没有返回唯一标识符,您应该检查它是否已经存在。为避免这种情况,您也可以为实体中的主键使用 UUID 生成器。
/**
* @ORM\Id
* @ORM\Column(type="guid", unique=true)
* @ORM\GeneratedValue(strategy="UUID")
*/
private $id;
如果您不喜欢这样,您可以使用 UUID_SHORT 创建一个新的自定义 ID 生成,并使用类似 this 的函数使其更短。
use Doctrine\ORM\Id\AbstractIdGenerator;
class UuidShortGenerator extends AbstractIdGenerator
{
public function generate(EntityManager $em, $entity)
{
$conn = $em->getConnection();
return $conn->query('SELECT UUID_SHORT()')->fetchColumn(0);
}
}
这里的问题是我不认为它提供了完整的可移植性。
关于php - 避免唯一约束与学说冲突的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33053079/