@Query(value = "LOCK TABLES mail WRITE", nativeQuery = true)
void lockTableForWriting();
@Query(value = "UNLOCK TABLES", nativeQuery = true)
void unlockTable();
但它们在lock
和unlock
上抛出了一个SQLGrammerException。
我无法获得行锁,因为行还不存在。或者,如果它确实存在,我不会更新任何东西,我只会不插入任何东西,而转移到其他东西。
还有其他情况,我希望用相同的事务id保存多个记录,所以我不能仅仅使列唯一并try/catch保存。
@Repository
public interface MailDao extends CrudRepository<Mail, Long> {
default Mail safeSave(Mail mail) {
return Optional.ofNullable(findByTransactionId(mail.getTransactionId()))
.orElseGet(() -> save(mail));
}
default Mail findByTransactionId(String transactionId) {
final List<Mail> mails = findAllByTransactionId(transactionId);
// Snipped code that selects a single entry to return
// If one can't be found, null is returned.
}
@Query(value = "SELECT m " +
" FROM Mail m " +
" WHERE m.transactionId = :transactionId ")
List<Mail> findAllByTransactionId(@Param("transactionId") String transactionId);
}
下面是mail
模型的一些内容:
@Entity
@Table(name = "mail")
public class Mail implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "mail_id", unique = true, nullable = false)
private Long mailId;
@Column(name = "transaction_id", nullable = false)
private String transactionId;
// Snipped code for other parameters,
// constructors, getters and setters.
}
下面是调用safeSave
的服务方法的一般思想。
@Service
public class MailServiceImpl implements MailService {
@Inject private final MailDao mailDao;
// Snipped injected other stuff
@Override
public void saveMailInfo(final String transactionId) {
Objects.requireNonNull(transactionId, "null transactionId passed to saveMailInfo");
if (mailDao.findByTransactionId(transactionId) != null) {
return;
}
// Use one of the injected things to do some lookup stuff
// using external services
if (mailDao.findByTransactionId(transactionId) != null) {
return;
}
// Use another one of the injected things to do more lookup
if (/* we've got everything we need */) {
final Mail mail = new Mail();
mail.setTransactionId(transactionId);
// Snipped code to set the rest of the stuff
mailDao.safeSave(mail);
}
}
}
我要防止的是对saveMailinfo
的两个几乎同时的调用导致数据库中的重复记录。
public interface MailDaoCustom {
Mail safeSave(Mail mail);
}
public interface MailDao extends CrudRepository<Mail, Long>, MailDaoCustom
则IMPL:
public class MailDaoImpl implements MailDaoCustom {
@Autowired private MailDao mailDao;
@Autowired private EntityManager em;
public Mail safeSave(Mail mail) {
Query lockTable = em.createNativeQuery("LOCK TABLES mail WRITE");
Query unlockTable = em.createNativeQuery("UNLOCK TABLES");
try {
lockTable.executeUpdate();
return Optional.ofNullable(mailDao.findByTransactionId(mail.getTransactionId()))
.orElseGet(() -> mailDao.save(mail));
} finally {
unlockTable.executeUpdate();
}
}
}
这是我在测试上面的时候得到的错误。这与我尝试在dao中使用查询来锁定和解锁方法时的情况相同:
SQL Error: 42000, SQLState: 42000
Syntax error in SQL statement "LOCK[*] TABLES MAIL WRITE "; SQL statement:
LOCK TABLES mail WRITE [42000-168]
不过,我的测试是使用单元测试完成的,单元测试使用的是H2内存数据库,而不是MySQL。不过,看起来H2可能并没有真正的表锁定。
public interface MailDaoCustom {
Mail safeSave(Mail mail);
}
public interface MailDao extends CrudRepository<Mail, Long>, MailDaoCustom
public class MailDaoImpl implements MailDaoCustom {
@Autowired private MailDao dao;
@Autowired private EntityManager em;
public Mail safeSave(Mail mail) {
// Store a new mail record only if one doesn't already exist.
Query uniqueInsert = em.createNativeQuery(
"INSERT INTO mail " +
" (transaction_id, ...) " +
"SELECT :transactionId, ... " +
" WHERE NOT EXISTS (SELECT 1 FROM mail " +
" WHERE transaction_id = :transactionId) ");
uniqueInsert.setParameter("transactionId", mail.getTransactionId());
// Snipped setting of the rest of the parameters in the query
uniqueInsert.executeUpdate();
// Now go get the record
Mail entry = dao.findByTransactionId(mail.getTransactionId());
// Detatch the entry so that we can attach the provided mail object later.
em.detach(entry);
// Copy all the data from the db entry into the one provided to this method
mail.setMailId(entry.getMailId());
mail.setTransactionId(entry.getTransactionId());
// Snipped setting of the rest of the parameters in the provided mail object
// Attach the provided object to the entity manager just like the save() method would.
em.merge(mail);
return mail;
}
}
它并不像我希望的那样干净,我担心我可能犯了一些错误,一些隐藏的东西,我不会发现,直到事情爆炸。但我们拭目以待。
我使用了insert INTO...WHERE NOT exists
查询和自定义回购。上面在更新2下列出了它,但我也把它放在这里,这样就更容易找到了。
public interface MailDaoCustom {
Mail safeSave(Mail mail);
}
更新了maildao
以实现它:
public interface MailDao extends CrudRepository<Mail, Long>, MailDaoCustom
然后impl如下所示:
public class MailDaoImpl implements MailDaoCustom {
@Autowired private MailDao dao;
@Autowired private EntityManager em;
public Mail safeSave(Mail mail) {
// Store a new mail record only if one doesn't already exist.
Query uniqueInsert = em.createNativeQuery(
"INSERT INTO mail " +
" (transaction_id, ...) " +
"SELECT :transactionId, ... " +
" WHERE NOT EXISTS (SELECT 1 FROM mail " +
" WHERE transaction_id = :transactionId) ");
uniqueInsert.setParameter("transactionId", mail.getTransactionId());
// Snipped setting of the rest of the parameters in the query
uniqueInsert.executeUpdate();
// Now go get the record
Mail entry = dao.findByTransactionId(mail.getTransactionId());
// Detach the entry so that we can attach the provided mail object later.
em.detach(entry);
// Copy all the data from the db entry into the one provided to this method
mail.setMailId(entry.getMailId());
mail.setTransactionId(entry.getTransactionId());
// Snipped setting of the rest of the parameters in the provided mail object
// Attach the provided object to the entity manager just like the save() method would.
em.merge(mail);
return mail;
}
}
如何获得整个Postgres表的锁,这样就没有其他进程可以更新表中的任何行(但仍然可以使用SELECT读取行)?我认为我想要的锁类型是EXCLUSIVE,但我不确定如何使用ecto查询为整个表获取这样的锁。 谢谢
我已经安装了DropWizard服务,以便在应用程序启动时自动进行任何液化迁移。 当我第一次启动我的Dropwizard服务时,我运行一个以提供信息。此调用还将创建和表,如果它们不存在作为副作用。 一旦在新的Oracle ATP DB上,它在调用listLocks期间创建锁表时抛出以下错误: 服务将抛出该异常,然后pod将重新启动并重复。我手动将该行添加到它试图插入的锁表中,然后下一次启动成功。
我们正在使用Flink表API在Flink应用程序中使用一个Kafka主题。 当我们第一次提交应用程序时,我们首先从我们的自定义注册表中读取最新的模式。然后使用Avro模式创建一个Kafka数据流和表。我的数据序列化器的实现与汇合模式注册表的工作方式类似,方法是检查模式ID,然后使用注册表。因此我们可以在运行时应用正确的模式。
我在一个带有服务器端渲染的react应用程序中使用react router dom,我正在寻找一种获得类似于的东西的方法,但除了路径名之外,我找不到任何东西。是否有任何方法可以使用react-router-dom获取原点?还是其他方式?
我有正则表达式来匹配以下模式, 链接到用例:https://regex101.com/r/wnp1k4/1 如何通过修改正则表达式获得相同的匹配?请帮助。 如果'X或x'在数字之前,订单号不应该被检测到。所以这工作正常。 X123456789 X123456789 x123-456-789 X123-456-789 123-456-789 需要修改正则表达式模式以获得如下所示的医嘱号列表的匹配项…
问题内容: 我想获得可用无线网络的列表。理想情况下,这将通过一些C调用进行,但是我不介意是否必须通过系统调用来混淆它。如果所需的C调用或程序不需要某些奇特的第三方包,甚至会更好。 互联网似乎建议我使用从命令行确实可以解决问题的技巧,但是我宁愿不需要root权限。我只想了解基础知识,什么也不想改变。 问题答案: 该无线工具包-它的iwlist是其中的一部分- 还包含一个无线工具帮助程序库。您需要包含