이것은 나에게 당황 스럽다. 나는 단서를 찾기 위해 수많은 포럼을 수색했다. postFlush 메소드에서, 새로운 세션을 사용하여 새로운 절전 모드 (v 3.3 - v.3.5 시도) 세션을 연다. 연결 풀링을 위해 c3p0 v. 0.9를 사용합니다. 새 트랜잭션을 시작하고 auditLog 객체를 저장 한 다음 트랜잭션을 커밋합니다. 이것은 모든 엔티티가 하나를 제외하고 아름답게 작동합니다. ChemoRegimen 엔티티를 삭제 한 후 auditLog를 커밋하려고 시도하면 응용 프로그램이 중지됩니다 (이 또한 생성 및 업데이트와 함께 발생합니다). (이것은 스윙 응용 프로그램입니다) 어떤 예외가 발생되지 않지만 스레드를 일시 중단에 나는 다음과 같은 스택 추적을 찾을 :Hibernate Interceptor를 사용하는 감사 로깅이 SocketInputStream.socketRead0에서 중단되는 이유는 무엇입니까?
Thread [AWT-EventQueue-0] (Suspended)
SocketInputStream.socketRead0(FileDescriptor, byte[], int, int, int) line: not available [native method]
SocketInputStream.read(byte[], int, int) line: 129
VisibleBufferedInputStream.readMore(int) line: 145
VisibleBufferedInputStream.ensureBytes(int) line: 114
VisibleBufferedInputStream.read() line: 73
PGStream.ReceiveChar() line: 274
QueryExecutorImpl.processResults(ResultHandler, int) line: 1660
QueryExecutorImpl.execute(Query[], ParameterList[], ResultHandler, int, int, int) line: 407
Jdbc4PreparedStatement(AbstractJdbc2Statement).executeBatch() line: 2737
NewProxyPreparedStatement.executeBatch() line: 1723
BatchingBatcher.doExecuteBatch(PreparedStatement) line: 70
BatchingBatcher(AbstractBatcher).executeBatch() line: 268
ActionQueue.executeActions(List) line: 266
ActionQueue.executeActions() line: 167
DefaultFlushEventListener(AbstractFlushingEventListener).performExecutions(EventSource) line: 321
DefaultFlushEventListener.onFlush(FlushEvent) line: 50
SessionImpl.flush() line: 1027
SessionImpl.managedFlush() line: 365
JDBCTransaction.commit() line: 137 **[This is where I commit the auditLog]**
MomsInterceptor.postFlush(Iterator) line: 254
DefaultFlushEventListener(AbstractFlushingEventListener).postFlush(SessionImplementor) line: 375
DefaultFlushEventListener.onFlush(FlushEvent) line: 51
SessionImpl.flush() line: 1027
SessionImpl.managedFlush() line: 365
JDBCTransaction.commit() line: 137
HibernateDAO.makeTransient(Entity) line: 119
ChemoServices.deleteChemoRegimen(ChemoRegimen, String, Session) line: 290
내가 9.0 JDBC4 드라이버와 백엔드로 PostgreSQL의 8.4을 사용하고 있습니다.
[첫째, chemo_regimen가 삭제]
2011-05-11 12:19:06 CDT moms postgres LOG: 00000: execute <unnamed>: delete from moms_chemo_regimen where crxreg_id=$1<BR>
....
[계단식 삭제의 많은] : [괄호 내 의견]을 postgresql.log 쇼
...
[그럼, 내 트랜잭션 인터셉터 세션에서 시작]
2011-05-11 12:19:06 CDT moms postgres LOG: 00000: execute S_1: BEGIN
2011-05-11 12:19:06 CDT moms postgres LOG: 00000: execute <unnamed>: select nextval ('moms_patient_change_log_seq')
는
2011-05-11 12:19:06 CDT moms postgres LOG: 00000: execute <unnamed>: insert into moms_patient_change_log (patclog_pat_id, patclog_action, patclog_reason, patclog_date, patclog_user_name, patclog_guid, patclog_id) values ($1, $2, $3, $4, $5, $6, $7)
2011-05-11 12:19:06 CDT moms postgres DETAIL: parameters: $1 = '17108', $2 = 'Deleted ChemoRegimen ABVD', $3 = NULL, $4 = '2011-05-11 12:19:06.813', $5 = 'daver', $6 = 'BFAA9D91-7A4E-835E-7A57-B72B2A79A4F1', $7 = '520'
[감사 로그 레코드가 삽입된다] 그게이다. 감사 로그 삽입 트랜잭션은 완료되지 않습니다. 화학 요법을 삭제하기위한 거래 역시 결코 커밋되지 않습니다. 나는 그것을 감사하지 않을 때 ChemoRegimen의 CRUD를 잘 수행 할 수 있습니다. ChemoRegimen 엔티티의 조각은 다음과 같습니다 : 어떤 도움을 크게 감상 할 수
public class MomsInterceptor extends EmptyInterceptor
{
private static Logger logger = Logger.getLogger(MomsInterceptor.class.getName());
private static Configuration configuration;
private static SessionFactory sessionFactory;
//Create the initial SessionFactory from the default configuration files
static
{
initSessionFactory();
}
public static void initSessionFactory()
{
try
{
configuration = new Configuration().configure();
sessionFactory = configuration.buildSessionFactory();
}
catch (Throwable ex)
{
// We have to catch Throwable, otherwise we will miss
// NoClassDefFoundError and other subclasses of Error
logger.severe("Building SessionFactory failed - " + ex.getMessage());
System.err.println("Building SessionFactory failed - " + ex.getMessage());
throw new ExceptionInInitializerError(ex.getMessage());
}
}
private Set<Auditable> inserts = new HashSet<Auditable>();
private Set<UpdatedEntity> updates = new HashSet<UpdatedEntity>();
private Set<Auditable> deletes = new HashSet<Auditable>();
private boolean audit;
public MomsInterceptor(boolean audit)
{
super();
this.audit = audit;
}
private class UpdatedEntity
{
private Auditable auditable;
private String[] propertyNames;
private Object[] currentState;
private Object[] previousState;
private Type[] types;
public UpdatedEntity(Auditable auditable, String[] propertyNames, Type[] types, Object[] currentState, Object[] previousState)
{
super();
this.auditable = auditable;
this.propertyNames = propertyNames;
this.currentState = currentState;
this.previousState = previousState;
this.types = types;
}
public Auditable getAuditable()
{
return auditable;
}
public String[] getPropertyNames()
{
return propertyNames;
}
public Object[] getCurrentState()
{
return currentState;
}
public Object[] getPreviousState()
{
return previousState;
}
public Type[] getTypes()
{
return types;
}
/**
* Return the previous value of the property name prop or null if the property name is not found.
* @param prop
* @return
*/
public Object getPrevious(String prop)
{
int i = 0;
for (String name : propertyNames)
{
if (prop.equals(name))
return previousState[i];
i++;
}
return null;
}
}
public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException
{
boolean modified = false;
if (entity instanceof MutableEntity) // Update create info.
{
MutableEntity me = (MutableEntity)entity;
int i = findPropertyNameIndex("createUser", propertyNames);
if (i >= 0)
state[i] = SessionController.userName;
i = findPropertyNameIndex("modifyUser", propertyNames);
if (i >= 0)
state[i] = SessionController.userName;
modified = true;
if (audit && entity instanceof Auditable)
inserts.add((Auditable)entity);
}
return modified;
}
private int findPropertyNameIndex(String name, String[] propertyNames)
{
int i = -1;
if (propertyNames.length == 0)
return i;
for (String p : propertyNames)
{
i++;
if (p.equals(name))
return i;
}
return -1;
}
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types)
throws CallbackException
{
boolean modified = false;
if (entity instanceof MutableEntity) // Update modify info.
{
MutableEntity me = (MutableEntity)entity;
int i = findPropertyNameIndex("modifyUser", propertyNames);
if (i >= 0)
currentState[i] = SessionController.userName;
i = findPropertyNameIndex("modifyDate", propertyNames);
if (i >= 0)
currentState[i] = new Date();
modified = true;
if (audit && entity instanceof Auditable)
updates.add(new UpdatedEntity((Auditable)entity, propertyNames, types, currentState, previousState));
}
return modified;
}
@Override
public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types)
{
if (audit && entity instanceof Auditable)
deletes.add((Auditable)entity);
}
@Override
public void postFlush(Iterator iterator) throws CallbackException
{
if (inserts.isEmpty() && deletes.isEmpty() && updates.isEmpty())
return;
Session session = sessionFactory.openSession();
session.setFlushMode(FlushMode.COMMIT);
session.beginTransaction();
try
{
String action = null;
for (Auditable entity : inserts)
{
action = "Created " + entity.getClass().getSimpleName() + " " + entity.toString();
session.save(new PatientChangeLog(entity.getPatient(), action, entity.getReason(), SessionController.userName));
}
for (Auditable entity : deletes)
{
action = "Deleted " + entity.getClass().getSimpleName() + " " + entity.toString();
session.save(new PatientChangeLog(entity.getPatient(), action, entity.getReason(), SessionController.userName));
}
for (UpdatedEntity entity : updates)
{
Auditable a = entity.getAuditable();
StringBuffer actionBuf = new StringBuffer("Updated " + a.getClass().getSimpleName() + " " + a.toString() + ": changed ");
int count = 0;
for (int i = 0; i < entity.getPropertyNames().length; i++)
{
String prop = entity.getPropertyNames()[i];
Type type = entity.getTypes()[i];
Object curValue = entity.getCurrentState()[i];
Object prevValue = entity.getPreviousState()[i];
//Don't consider the id field or the metadata fields.
if (prop.equals("id") || prop.equals("createUser") || prop.equals("createDate") || prop.equals("modifyUser")
|| prop.equals("modifyDate") || prop.equals("guid"))
continue;
if (prevValue == null)
prevValue = new String("");
if (curValue == null)
curValue = new String("");
if (!prevValue.equals(curValue))
{
if (count > 0)
actionBuf.append(" and ");
actionBuf.append(prop).append(" from '").append(prevValue).append("' to '").append(curValue).append("'");
count++;
}
}
Patient p = (Patient)entity.getPrevious("patient"); //In case the patient is changed, tie it to the previous patient.
session.save(new PatientChangeLog(p, actionBuf.toString(), a.getReason(), SessionController.userName));
}
session.getTransaction().commit();
}
catch (HibernateException e)
{
try
{
session.getTransaction().rollback();
}
catch (Exception hex)
{
throw new RuntimeException(hex);
}
throw new RuntimeException(e);
}
finally
{
inserts.clear();
updates.clear();
deletes.clear();
session.close();
}
}
}
:
public class ChemoRegimen extends MOMSEntity implements Auditable
{
public static final String UNSCHEDULED = "UNSCHEDULED";
private Date date = new Date();
private Patient patient;
private WorkingProtocol protocol;
private Physician approvingPhysician;
private boolean canChangeCycles;
private List<ChemoEncounter> chemoEncounters = new ArrayList<ChemoEncounter>();
private boolean complete;
private Icdm icdm;<BR>
...<BR>
}
이 내 인터셉터입니다.
감사합니다 axtavt 및 @SteveHall. 나는 최대 절전 모드 이벤트를 살펴볼 것이다. – David
axtavt, Envers를 사용하지 않고 감사 로깅을 구현하기 위해 이벤트를 사용하는 데 필요한 모든 설명서를 알고 있습니까? Envers는 주석을 사용하지 않기 때문에 Hibernate와 관련된 주요 변경 사항을 요구합니다. 이런 문서를 찾을 수 없었습니다. – David