@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)。您需要处理缩进不回滚的父调用方方法的异常。