createNativeQuery()
如果在以下情况下使用,则可以安全地阻止SQL注入:
@ManagedBean
@ViewScoped
public class UserController {
@PersistenceContext
private EntityManager em;
public User register(User u) {
Query query = em.createNativeQuery("SELECT r1_register(?,?,?,?,?,?,?)");
short i = 0;
query.setParameter(++i, u.getUsername());
query.setParameter(++i, u.getPassword());
query.setParameter(++i, u.getName());
query.setParameter(++i, u.getSurname());
query.setParameter(++i, u.getEmail());
query.setParameter(++i, u.getBirthdate());
query.setParameter(++i, u.getPhoneNumber());
int id = (int) query.getSingleResult();
if (id != 0) u.setIduser(id);
return u;
}
}
r1_register
是一个存储函数,它执行INSERT并返回新插入用户的id。这是否相同:
public User register(User u) {
em.persist(u);
// get the last inserted id (user id must be @Generated)
em.flush(); // user id set here
return u;
}
u
在两种情况下均由用户填写。最后是默认启动的交易吗?
编辑:例程:
CREATE DEFINER=`root`@`localhost` FUNCTION `r1_register`(username VARCHAR(45),
_password VARCHAR(45),
_name VARCHAR(45),
surname VARCHAR(45),
_email VARCHAR(45),
_birthdate DATE,
phone_number VARCHAR(10) ) RETURNS int(11)
BEGIN
-- Adds a new user.
-- START TRANSACTION; -- Begin a transaction -- NOT ALLOWED
-- http://stackoverflow.com/questions/16969875/
IF r1_check_unique_username(username)=0 THEN
RETURN 0;
END IF;
INSERT IGNORE INTO `hw1_db`.`users` (`username`, `password`, `name`, `surname`, `email`, `birthdate`, `phone_number`)
VALUES (username, _password, _name, surname, _email, _birthdate, phone_number);
-- see: http://stackoverflow.com/a/5939840/281545
-- The drawback to this approach is that you cannot go back and use
-- ids wasted because of failed attempts to INSERT IGNORE in the event
-- of a duplicate key. Shouldn't be a problem for us as we check.
-- /Transaction
-- IF ROW_COUNT() > 0 THEN
-- ROW_COUNT() returns the number of rows updated/inserted/deleted
-- COMMIT; -- Finalize the transaction
-- ELSE
-- ROLLBACK; -- Revert all changes made before the transaction began
-- END IF;
RETURN LAST_INSERT_ID();
END
答案 0 :(得分:1)
这取决于r1_register
实际上在做什么。如果它只是保存用户而不是其他任何东西,那么它们是等价的,因为那是EntityManager#persist
正在做的事情。但是,如果DB函数正在执行某些安全检查或写入其他表,那么您需要在JPA中实现它。用于插入User
和获取ID的顺便说一句代码应为
public User register(User u) {
em.getTransaction().begin();
em.persist(u);
em.getTransaction().commit();
int id = u.getId();
return u;
}
但是,如果在调用EntityManager#flush
方法后需要该id,则不必调用register
,在每个事务结束时执行flush。