Spring + Hibernate를 사용할 때 이상한 캐시가 있습니다.Hibernate + Spring에 의한 예기치 않은 캐시
라인 A는 2012 년
라인 B는 올해 찾는 DB에서 그것을 얻을 올해와 데이터베이스에 데이터의 새로운 행을 삽입하다 2012 년
선 C 업데이트 해 1970 년에
라인 D는 올해 여전히 2012입니다 발견 , 나는 이것이 왜 일어날 지 이해하지 못한다. 그러나 B 행을 주석으로 처리한다면 D 행은 1970 년이되고 어떤 종류의 캐시처럼 보입니다. 또는 findLock()에서 getCurrentSession() 대신 openSession()을 사용하면 D 행도 1970이됩니다. abybody가이 동작을 설명 할 수 있습니까?
테스트 드라이브
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext-Test.xml")
@TransactionConfiguration(defaultRollback = true,transactionManager="transactionManager")
@Transactional
public class OperationLockDAOTest {
@Autowired
private OperationLockDAO operationLockDAO;
@Autowired
private APIOperationDAO apiOperationDAO;
private APIOperation operation;
@Before
public void setup() {
operation = apiOperationDAO.findOperationById(Constants.OP_CREATE_SUBSCRIBER);
}
@Test
public void testAddNewLockAndReleaseLock() throws DBException{
String userKey = "testUserKey1" + Math.random();
boolean bGetLock = operationLockDAO.lockOperationByUser(userKey, operation);//line A, insert 2012
List<OperationLock> locks1 = operationLockDAO.findLock(userKey, operation);//line B
OperationLock lock1 = locks1.get(0);
Calendar cb = Calendar.getInstance();
cb.setTime(lock1.getModifytime());//get 2012
operationLockDAO.unlockOperationByUser(userKey, operation);//line C, update to 1970
List<OperationLock> locks2 = operationLockDAO.findLock(userKey, operation);//line D
OperationLock lock2 = locks2.get(0);
Calendar cr = Calendar.getInstance();
cr.setTime(lock2.getModifytime());
int crYear = cr.get(Calendar.YEAR);// still get 2012
assertTrue(crYear == Constants.LongBeforeYear);//assert time stamp of lock is set to 1970 after release
}
}
나는 문제가 최대 절전 모드 (및 JPA가) 정말 네이티브 SQL, 특히 SQL 업데이트 쿼리에 대한 인터페이스로 구성되지 않는 것입니다 믿는 것
@Repository("operationLockDAOImpl")
public class OperationLockDAOImpl implements OperationLockDAO{
protected static final Logger logger = LoggerFactory.getLogger(OperationLockDAOImpl.class);
/**
* return true - this operation is not locked by another thread, lock behavior is successful this time
* false - this operation is locked by another thread, lock behavior failed this time
*/
@SuppressWarnings("unchecked")
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public boolean lockOperationByUser(String userKey, APIOperation lockoperation) {
String selecSsql = "select * from operation_lock where userKey=:userKey and lockoperationId=:lockoperationId";
Session session = this.factory.getCurrentSession();
Query selectQuery = session.createSQLQuery(selecSsql).addEntity(OperationLock.class);
selectQuery.setString("userKey", userKey);
selectQuery.setLong("lockoperationId", lockoperation.getId());
List<OperationLock> operationLockList = selectQuery.list();
if(operationLockList == null || operationLockList.size() == 0){//no record for this userKey and operation, insert one anyway
String insertSql = "insert into operation_lock(`userKey`,`lockoperationId`,`modifytime`) values (:userKey, :lockoperationId, :updateTime)";
Query insertQuery = session.createSQLQuery(insertSql);
insertQuery.setString("userKey", userKey);
insertQuery.setLong("lockoperationId", lockoperation.getId());
insertQuery.setTimestamp("updateTime", new Date());
insertQuery.executeUpdate();
return true;
} else {
return false;
}
}
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public void unlockOperationByUser(String userKey, APIOperation lockoperation) {
Date currentTime = new Date();
Calendar time = Calendar.getInstance();
time.setTime(currentTime);
time.set(Calendar.YEAR, Constants.LongBeforeYear);//it's long before
String sql = "update operation_lock set modifytime=:updatetime where userKey=:userKey and lockoperationId=:lockoperationId";
Session session = this.factory.getCurrentSession();
Query query = session.createSQLQuery(sql);
query.setTimestamp("updatetime", time.getTime());
query.setString("userKey", userKey);
query.setLong("lockoperationId", lockoperation.getId());
query.executeUpdate();
}
@SuppressWarnings("unchecked")
@Transactional(isolation = Isolation.SERIALIZABLE)
@Override
public List<OperationLock> findLock(String userKey, APIOperation lockoperation) {
String sql = "select * from operation_lock where userKey=:userKey and lockoperationId=:lockoperationId";
// Session session = this.factory.openSession();
Session session = this.factory.getCurrentSession();
Query query = session.createSQLQuery(sql).addEntity(OperationLock.class);
query.setString("userKey", userKey);
query.setLong("lockoperationId", lockoperation.getId());
List<OperationLock> result = query.list();
// session.close();
return result;
}
}
오, openSession()은 새로운 1 차 캐시를 생성하기 때문에 작동한다. – Pace