@Transactional:有没有一种方法可以让hibernate在父事务失败时保持子事务
@Transactional : Is there a way that hibernate can persist child transacttion when parent fails
我是 Spring-Hibernate 的新手,我的问题是:事务没有在 table 中保存数据。但也不会抛出任何异常。 来自行
Long id = logTransactionFileUpload(fileMetdataBean);
在函数 "logClientFile" 中(在下面列出的 "Transactional" 注释 class/service class 中),我看到返回的 ID 但数据没有出现在 table. .
Finding 是: 这是嵌套事务,由于父级在 JobRunnerServiceImpl class 中的 "msgProducer.send( message, jmsConnectInfo )" 中有异常而被回滚,在 submitJob 方法中-表示在数据库插入之后。 有没有办法让 hibernate 在父事务失败时保持子事务?
我不怀疑我的 spring/hibernate 配置,因为从其他部分保存的配置工作正常。只有这部分是问题。
仅供参考:
如果我打开(在下面列出的 DAO impl class 中)
//getCurrentSession().flush();
//getCurrentSession().getTransaction().commit();
然后数据显示在 table.But 中,当使用 @transactional 时,此提交和刷新不应该存在。
我的@Transactional 注释class:
@Service("jobRunnerService")
@Transactional
public class JobRunnerServiceImpl implements JobRunnerService
{
private static final Logger LOG = LoggerFactory.getLogger( MethodHandles.lookup().lookupClass() );
@Autowired
@Qualifier("fileLoggerDao")
private IFileLoggerDAO fileLoggerDAO;
@Autowired
@Qualifier("fileMetaDataDao")
private IGenericDAO<FileMetaDataBean,Long> fileMetaDataDAO;
public void submitJob(String serviceName, String filePath, long clientId, long layoutId, String audienceId,
boolean isCA)
{
Map<String, String> parameters = new HashMap<String, String>();
try
{
..... doing something............
LOG.info( "Logging file information in FILE_META_DATA table... " );
String loggedFile = logClientFile( fileName, FACEBOOK_FILE_TYPE, fileExt, clientId, tpList );
..... doing something............
LOG.info( " Submitting job to JMS Q...." );
msgProducer.send( message, jmsConnectInfo );
//test code for the receiver to see if sent messages are received by receiver
//WildFlyJmsQueueReceive receiver = new WildFlyJmsQueueReceive();
//receiver.receiveMessagesFromQueue();
}
catch ( Exception e )
{
String msg = "Error in JobRunnerServiceImpl.submitJob";
LOG.error(msg,e);
throw new RuntimeException(msg,e);
}
}
private String logClientFile( String fileName, String fileType, String fileExt, long clientId, List<ToolkitPropertyBean> tpList )
{
ApplicationEnvironment enviro;
try
{
..... doing something............
//insert record in FILE_META_DATA table
FileMetaDataBean fileMetdataBean = new FileMetaDataBean(fileId, new Long(fileTypeID), fileName, fbFilePickUpDir +java.nio.file.FileSystems.getDefault().getSeparator()+ currentFile.getName(), receivedDate,new Long( FileUtilities.getRecordCount( currentFile ) ).longValue(), clientId);
Long id = logTransactionFileUpload(fileMetdataBean);
return null;
}
catch ( Exception e )
{
String msg = "Inside JobRunnerServiceImpl.logClientFile - Unable to log client file";
LOG.error(msg,e);
throw new RuntimeException(msg,e);
}
}
private Long logTransactionFileUpload(FileMetaDataBean bean)
{
return (Long)fileMetaDataDAO.save(bean);
}
}
我的豆子:
@Entity
@Table(name="FILE_META_DATA", schema = "OAP_META_OWNER", uniqueConstraints = {
@UniqueConstraint(columnNames = "file_meta_data_id"),
})
//@SequenceGenerator(name="file_meta_seq", sequenceName="file_meta_seq")
public class FileMetaDataBean implements Serializable
{
private long fileMetaDataId;
private Long fileType;
private String fileName;
private String originaFileName;
private Date receivedDt;
private Long recordCount;
private Long clientId;
public FileMetaDataBean(){}
public FileMetaDataBean( long fileMetaDataId, Long fileType, String fileName, String originaFileName, Date receivedDt,
long recordCount, long clientId )
{
super();
this.fileMetaDataId = fileMetaDataId;
this.fileType = fileType;
this.fileName = fileName;
this.originaFileName = originaFileName;
this.receivedDt = receivedDt;
this.recordCount = recordCount;
this.clientId = clientId;
}
@Id
// @GeneratedValue(strategy = GenerationType.AUTO, generator = "file_meta_seq")
@Column(name = "file_meta_data_id", unique = true, nullable = false)
public long getFileMetaDataId()
{
return fileMetaDataId;
}
public void setFileMetaDataId( long fileMetaDataId )
{
this.fileMetaDataId = fileMetaDataId;
}
@Column(name = "file_type_id", unique = false, nullable = false)
public Long getFileType()
{
return fileType;
}
public void setFileType( Long fileType )
{
this.fileType = fileType;
}
@Column(name = "file_name", unique = false, nullable = false)
public String getFileName()
{
return fileName;
}
public void setFileName( String fileName )
{
this.fileName = fileName;
}
@Column(name = "original_file_name", unique = false, nullable = false)
public String getOriginaFileName()
{
return originaFileName;
}
public void setOriginaFileName( String originaFileName )
{
this.originaFileName = originaFileName;
}
@Column(name = "received_dt", unique = false, nullable = false)
public Date getReceivedDt()
{
return receivedDt;
}
public void setReceivedDt( Date receivedDt )
{
this.receivedDt = receivedDt;
}
@Column(name = "record_count", unique = false, nullable = false)
public Long getRecordCount()
{
return recordCount;
}
public void setRecordCount( Long recordCount )
{
this.recordCount = recordCount;
}
@Column(name = "client_id", unique = false, nullable = false)
public Long getClientId()
{
return clientId;
}
public void setClientId( Long clientId )
{
this.clientId = clientId;
}
}
DAO 接口
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;
public interface IGenericDAO< Entity extends Serializable, ID extends Serializable >
{
Entity getById( ID id );
List<Entity> getAll();
List<Entity> getAll( String contraints);
List<Entity> search( Map<String, Object> parms );
ID save( Entity entity );
void saveOrUpdate( Entity entity );
void update( Entity entity );
void delete( Entity entity );
void deleteById( ID id );
void setSessionFactory( SessionFactory sessionFactory );
void setEntity( final Class clazz );
}
DAO 实现:
@SuppressWarnings(value = "unchecked")
public class GenericDAOImpl<Entity extends Serializable, ID extends Serializable>
implements IGenericDAO<Entity, ID> {
protected Class<Entity> clazz;
public GenericDAOImpl(Class<Entity> clazz) {
System.out.println(this.getClass().getSimpleName() + " called");
this.clazz = clazz;
}
@Autowired
@Qualifier("sessionFactory")
protected SessionFactory sessionFactory;
@Override
public Entity getById(ID id) {
System.out.println("GenericHibernateDAO.getById called with id: " + id);
return (Entity) getCurrentSession().get(clazz, id);
}
@Override
public List<Entity> getAll() {
System.out.println("GenericHibernateDAO.getAll called");
return getCurrentSession().createCriteria(clazz.getName()).list();
// return getCurrentSession().createQuery("from " + clazz.getName()).list();
}
@Override
public List<Entity> getAll(String contraints) {
System.out.println("GenericHibernateDAO.getAll called. Constraint : " + contraints);
return getCurrentSession().createQuery("from " + clazz.getName() + " " + contraints ).list();
}
@Override
public List search(Map<String, Object> parms) {
Criteria criteria = getCurrentSession().createCriteria(clazz);
for (String field : parms.keySet()) {
criteria.add(Restrictions.ilike(field, parms.get(field)));
}
return criteria.list();
}
@Override
public ID save(Entity entity) {
Serializable id = null;
try
{
id = getCurrentSession().save(entity);
}
catch(RuntimeException e)
{
throw e;
}
// getCurrentSession().flush();
// getCurrentSession().getTransaction().commit();
return (ID)id;
}
@Override
public void saveOrUpdate(Entity entity) {
getCurrentSession().saveOrUpdate(entity);
getCurrentSession().flush();
getCurrentSession().getTransaction().commit();
}
@Override
public void update(Entity entity) {
getCurrentSession().update(entity);
getCurrentSession().flush();
getCurrentSession().getTransaction().commit();
}
@Override
public void delete(Entity entity) {
getCurrentSession().delete(entity);
getCurrentSession().flush();
getCurrentSession().getTransaction().commit();
}
@Override
public void deleteById(ID id) {
delete(getById(id));
}
protected Session getCurrentSession() {
// return sessionFactory.openSession();
return sessionFactory.getCurrentSession();
}
@Override
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public void setEntity(final Class clazz) {
this.clazz = clazz;
}
}
您可以使用
noRollbackFor
属性 的交易注释,例如@Transactional(noRollbackFor=SendMsgFailureException.class)
。您需要处理缩进不回滚的父调用方方法的异常。
我是 Spring-Hibernate 的新手,我的问题是:事务没有在 table 中保存数据。但也不会抛出任何异常。 来自行
Long id = logTransactionFileUpload(fileMetdataBean);
在函数 "logClientFile" 中(在下面列出的 "Transactional" 注释 class/service class 中),我看到返回的 ID 但数据没有出现在 table. .
Finding 是: 这是嵌套事务,由于父级在 JobRunnerServiceImpl class 中的 "msgProducer.send( message, jmsConnectInfo )" 中有异常而被回滚,在 submitJob 方法中-表示在数据库插入之后。 有没有办法让 hibernate 在父事务失败时保持子事务?
我不怀疑我的 spring/hibernate 配置,因为从其他部分保存的配置工作正常。只有这部分是问题。
仅供参考:
如果我打开(在下面列出的 DAO impl class 中)
//getCurrentSession().flush();
//getCurrentSession().getTransaction().commit();
然后数据显示在 table.But 中,当使用 @transactional 时,此提交和刷新不应该存在。
我的@Transactional 注释class:
@Service("jobRunnerService")
@Transactional
public class JobRunnerServiceImpl implements JobRunnerService
{
private static final Logger LOG = LoggerFactory.getLogger( MethodHandles.lookup().lookupClass() );
@Autowired
@Qualifier("fileLoggerDao")
private IFileLoggerDAO fileLoggerDAO;
@Autowired
@Qualifier("fileMetaDataDao")
private IGenericDAO<FileMetaDataBean,Long> fileMetaDataDAO;
public void submitJob(String serviceName, String filePath, long clientId, long layoutId, String audienceId,
boolean isCA)
{
Map<String, String> parameters = new HashMap<String, String>();
try
{
..... doing something............
LOG.info( "Logging file information in FILE_META_DATA table... " );
String loggedFile = logClientFile( fileName, FACEBOOK_FILE_TYPE, fileExt, clientId, tpList );
..... doing something............
LOG.info( " Submitting job to JMS Q...." );
msgProducer.send( message, jmsConnectInfo );
//test code for the receiver to see if sent messages are received by receiver
//WildFlyJmsQueueReceive receiver = new WildFlyJmsQueueReceive();
//receiver.receiveMessagesFromQueue();
}
catch ( Exception e )
{
String msg = "Error in JobRunnerServiceImpl.submitJob";
LOG.error(msg,e);
throw new RuntimeException(msg,e);
}
}
private String logClientFile( String fileName, String fileType, String fileExt, long clientId, List<ToolkitPropertyBean> tpList )
{
ApplicationEnvironment enviro;
try
{
..... doing something............
//insert record in FILE_META_DATA table
FileMetaDataBean fileMetdataBean = new FileMetaDataBean(fileId, new Long(fileTypeID), fileName, fbFilePickUpDir +java.nio.file.FileSystems.getDefault().getSeparator()+ currentFile.getName(), receivedDate,new Long( FileUtilities.getRecordCount( currentFile ) ).longValue(), clientId);
Long id = logTransactionFileUpload(fileMetdataBean);
return null;
}
catch ( Exception e )
{
String msg = "Inside JobRunnerServiceImpl.logClientFile - Unable to log client file";
LOG.error(msg,e);
throw new RuntimeException(msg,e);
}
}
private Long logTransactionFileUpload(FileMetaDataBean bean)
{
return (Long)fileMetaDataDAO.save(bean);
}
}
我的豆子:
@Entity
@Table(name="FILE_META_DATA", schema = "OAP_META_OWNER", uniqueConstraints = {
@UniqueConstraint(columnNames = "file_meta_data_id"),
})
//@SequenceGenerator(name="file_meta_seq", sequenceName="file_meta_seq")
public class FileMetaDataBean implements Serializable
{
private long fileMetaDataId;
private Long fileType;
private String fileName;
private String originaFileName;
private Date receivedDt;
private Long recordCount;
private Long clientId;
public FileMetaDataBean(){}
public FileMetaDataBean( long fileMetaDataId, Long fileType, String fileName, String originaFileName, Date receivedDt,
long recordCount, long clientId )
{
super();
this.fileMetaDataId = fileMetaDataId;
this.fileType = fileType;
this.fileName = fileName;
this.originaFileName = originaFileName;
this.receivedDt = receivedDt;
this.recordCount = recordCount;
this.clientId = clientId;
}
@Id
// @GeneratedValue(strategy = GenerationType.AUTO, generator = "file_meta_seq")
@Column(name = "file_meta_data_id", unique = true, nullable = false)
public long getFileMetaDataId()
{
return fileMetaDataId;
}
public void setFileMetaDataId( long fileMetaDataId )
{
this.fileMetaDataId = fileMetaDataId;
}
@Column(name = "file_type_id", unique = false, nullable = false)
public Long getFileType()
{
return fileType;
}
public void setFileType( Long fileType )
{
this.fileType = fileType;
}
@Column(name = "file_name", unique = false, nullable = false)
public String getFileName()
{
return fileName;
}
public void setFileName( String fileName )
{
this.fileName = fileName;
}
@Column(name = "original_file_name", unique = false, nullable = false)
public String getOriginaFileName()
{
return originaFileName;
}
public void setOriginaFileName( String originaFileName )
{
this.originaFileName = originaFileName;
}
@Column(name = "received_dt", unique = false, nullable = false)
public Date getReceivedDt()
{
return receivedDt;
}
public void setReceivedDt( Date receivedDt )
{
this.receivedDt = receivedDt;
}
@Column(name = "record_count", unique = false, nullable = false)
public Long getRecordCount()
{
return recordCount;
}
public void setRecordCount( Long recordCount )
{
this.recordCount = recordCount;
}
@Column(name = "client_id", unique = false, nullable = false)
public Long getClientId()
{
return clientId;
}
public void setClientId( Long clientId )
{
this.clientId = clientId;
}
}
DAO 接口
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Transactional;
public interface IGenericDAO< Entity extends Serializable, ID extends Serializable >
{
Entity getById( ID id );
List<Entity> getAll();
List<Entity> getAll( String contraints);
List<Entity> search( Map<String, Object> parms );
ID save( Entity entity );
void saveOrUpdate( Entity entity );
void update( Entity entity );
void delete( Entity entity );
void deleteById( ID id );
void setSessionFactory( SessionFactory sessionFactory );
void setEntity( final Class clazz );
}
DAO 实现:
@SuppressWarnings(value = "unchecked")
public class GenericDAOImpl<Entity extends Serializable, ID extends Serializable>
implements IGenericDAO<Entity, ID> {
protected Class<Entity> clazz;
public GenericDAOImpl(Class<Entity> clazz) {
System.out.println(this.getClass().getSimpleName() + " called");
this.clazz = clazz;
}
@Autowired
@Qualifier("sessionFactory")
protected SessionFactory sessionFactory;
@Override
public Entity getById(ID id) {
System.out.println("GenericHibernateDAO.getById called with id: " + id);
return (Entity) getCurrentSession().get(clazz, id);
}
@Override
public List<Entity> getAll() {
System.out.println("GenericHibernateDAO.getAll called");
return getCurrentSession().createCriteria(clazz.getName()).list();
// return getCurrentSession().createQuery("from " + clazz.getName()).list();
}
@Override
public List<Entity> getAll(String contraints) {
System.out.println("GenericHibernateDAO.getAll called. Constraint : " + contraints);
return getCurrentSession().createQuery("from " + clazz.getName() + " " + contraints ).list();
}
@Override
public List search(Map<String, Object> parms) {
Criteria criteria = getCurrentSession().createCriteria(clazz);
for (String field : parms.keySet()) {
criteria.add(Restrictions.ilike(field, parms.get(field)));
}
return criteria.list();
}
@Override
public ID save(Entity entity) {
Serializable id = null;
try
{
id = getCurrentSession().save(entity);
}
catch(RuntimeException e)
{
throw e;
}
// getCurrentSession().flush();
// getCurrentSession().getTransaction().commit();
return (ID)id;
}
@Override
public void saveOrUpdate(Entity entity) {
getCurrentSession().saveOrUpdate(entity);
getCurrentSession().flush();
getCurrentSession().getTransaction().commit();
}
@Override
public void update(Entity entity) {
getCurrentSession().update(entity);
getCurrentSession().flush();
getCurrentSession().getTransaction().commit();
}
@Override
public void delete(Entity entity) {
getCurrentSession().delete(entity);
getCurrentSession().flush();
getCurrentSession().getTransaction().commit();
}
@Override
public void deleteById(ID id) {
delete(getById(id));
}
protected Session getCurrentSession() {
// return sessionFactory.openSession();
return sessionFactory.getCurrentSession();
}
@Override
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public void setEntity(final Class clazz) {
this.clazz = clazz;
}
}
您可以使用
noRollbackFor
属性 的交易注释,例如@Transactional(noRollbackFor=SendMsgFailureException.class)
。您需要处理缩进不回滚的父调用方方法的异常。