简体   繁体   中英

Associated Entity does not get saved in transaction

I am fairly new to entity frameworks, and don't understand why my entity does not get saved correctly.

edit:

I will try to out this test code soon, and see if it works:

@Transactional
public void doConvert(String lakoKod) {
    LsZFutelszHavi futelszHavi = new LsZFutelszHavi();
    //Give it values like:
    futelszHavi.setOrigKorrOssz(new BigDecimal(500));
    LsTLako lako = lsTLakoRepository.findOneByLakoKod(lakoKod);
    LsZFutelsz futelsz = lsZFutelszRepository.findOneByLsTLako(lako);
    //The modification which not get saved into tha Firebird table in the original code. Will it be saved now?
    futelsz.setSzezVegenBefOssz(new BigDecimal(100));
    futelszHavi.setLsZFutelsz(futelsz);
    lsZFutelszHaviRepository.save(futelszHavi);
}

I am trying to convert from an old DBASE database, to a Firebird database. The Firebird database have it's tables mapped by entities. I read a DBASE table, then convert it row by row.

I use @Transactional, to either save all converted entities of the DBASE table, or save none.

I managed to convert every table correctly into the new database except one.

In the other tables, I only had to save one entity per record, and did not have to modify other type of entities. I usually had to create a Type X entity, connect it to a Type Y entity, then save. For save, I use a repository for the entity (an org.springframework.data.repository.PagingAndSortingRepository if it matters)

In that particular DBASE table, I have to create one entity of Type A, connect it to a Type B entity, modify the Type B entity, then save. The problem is, that Type B entity modification does not get saved into the Firebird table. Again, I use a repository to save the entity.

To get the Type B entity, I use it's repository's method:

LsZFutelsz findOneByLsTLako(LsTLako lsTLako); 

I guessed, that maybe if I save this Type B entity with it's own repository, it would get modified in the database correctly. It did not help.

Please tell me if additional information is needed.

I copy my slightly altered code here (removed some logging, added some comments). LsZFutelszHavi is the Type A EntityClass, LsZFutelsz is type B EntityClass.

The Konverter abstract class. It is inherited for every DBASE table

public abstract class Konverter<RepositoryType extends     CrudRepository<EntityType,Integer>, EntityType> {
protected String dbfPath;
protected DBaseTable sourceTable = null;
protected Logger logger;
protected RepositoryType repository;
protected String dBaseEncoding = DBaseTable.CP852;

public Konverter(String dbfPath, Logger logger, RepositoryType repository) {
    this.dbfPath = dbfPath;
    this.logger = logger;
    this.repository = repository;
}

/*
This method should be called, to start converting
*/
@Transactional
public void konvert() {
    try {
        /*It loads the DBASE database*/     
        File sourceFile = new File(fileName);
        sourceTable = new DBaseTable(sourceFile, dBaseEncoding);
        sourceTable.open(IfNonExistent.ERROR);

        Iterator<Record> recordIterator = sourceTable.recordIterator();            
        int count = 0;
        try {
            /*Converts the database table row by row*/
            count = konvertSorok(recordIterator);
        } catch (Exception e) {
            throw e;
        } finally {
            sourceTable.close();
        }
    }
    catch (CorruptedTableException | IOException | RuntimeException e) {
        logger.error(QsLoggerUtils.getStackTraceString(e));//e.printStackTrace();
    }

}

private int konvertSorok(Iterator<Record> recordIterator) {
    int count = 0;
    /*Converts the database table row by row*/
    while(recordIterator.hasNext())
    {
        Record record = recordIterator.next();
        /* Converting one row */
        List<EntityType> entityIterable = konvertToEntity( record );

        for (EntityType entityType : entityIterable) {
            repository.save(entityType);                
        }
        count++;
    }       
    return count;
}

/**
 * This should be implemented in the child method
 * @param record
 * @return
 */
protected abstract List<EntityType> konvertToEntity(Record record); 
}

The child Class, that implmenets konvertToEntity method.

public class Konvert14FutelszHavi extends Konverter<LsZFutelszHaviRepository,LsZFutelszHavi> {

private static Logger logger = LoggerFactory.getLogger(Konvert12Futalany.class);

LsZFutelszHaviRepository lsZFutelszHaviRepository;
LsTLakoRepository lsTLakoRepository; 
LsZFutelszRepository lsZFutelszRepository;
LsTEvhoRepository lsTEvhoRepository;


@Autowired
public Konvert14FutelszHavi(LsZFutelszHaviRepository lsZFutelszHaviRepository,
                            LsTLakoRepository lsTLakoRepository,
                            LsZFutelszRepository lsZFutelszRepository,
                            LsTEvhoRepository lsTEvhoRepository) throws IOException {
    super(DBaseTable.chkFile(AppKonvertLax.PATH_LSZBF, AppKonvertLax.SOURCE_FILE_FUTELSZ_HAVI), logger, lsZFutelszHaviRepository);
    dBaseEncoding = DBaseTable.CP1250;
    this.lsTLakoRepository = lsTLakoRepository;
    this.lsZFutelszHaviRepository = lsZFutelszHaviRepository;
    this.lsZFutelszRepository = lsZFutelszRepository;
    this.lsTEvhoRepository = lsTEvhoRepository;
}

@Override
protected List<LsZFutelszHavi> konvertToEntity(Record record) {
    String ukod     = record.getStringValue("UKOD").substring(1).trim();        
    BigDecimal ekaptam  = new BigDecimal(record.getNumberValue("EKAPTAM").toString());        
    BigDecimal efutkul  = new BigDecimal(record.getNumberValue("EFUTKUL").toString());              

    ArrayList<LsZFutelszHavi> returnArray = new ArrayList<LsZFutelszHavi>();
    LsTLako lsTLako = lsTLakoRepository.findOneByLakoKod(ukod);
    LsZFutelsz lsZFutelsz = lsZFutelszRepository.findOneByLsTLako(lsTLako);
    if (lsZFutelsz == null) {
        return returnArray;
    }
    /* Here is the modification in the lsZFutelsz (Type B) entity */
    lsZFutelsz.setSzezVegenBefOssz(ekaptam);

    /* From 10th month to 4th */
    for (int i=10; i!=5; i++) {
        if (i==13) { 
            i = 1;
        }
        String keyNumber = Integer.toString(i);
        if (keyNumber.length() == 1) {
            keyNumber = "0" + keyNumber;
        }
        BigDecimal fk = new BigDecimal(record.getNumberValue("FK_"+keyNumber).toString());
        LsZFutelszHavi lsZFutelszHavi = new LsZFutelszHavi();
        LsTEvho lsTEvho = lsTEvhoRepository.findOneByEvAndHo(2014, i);
        lsZFutelszHavi.setLsTEvho(lsTEvho);
        lsZFutelszHavi.setFizKorrOssz(fk);
        lsZFutelszHavi.setOrigKorrOssz(efutkul);
        /* This should be enough to save the lsZFutelsz entity modification I would think */
        lsZFutelszHavi.setLsZFutelsz(lsZFutelsz);
        returnArray.add(lsZFutelszHavi);
    }

    /* Even this does not help */
    lsZFutelszRepository.save(lsZFutelsz);

    return returnArray;
}

}

Repository for the Type B entity

@RepositoryRestResource(collectionResourceRel = LsZFutelszHavi.VERB_FUTELSZ, path = LsZFutelszHavi.VERB_FUTELSZ)
public interface LsZFutelszRepository extends PagingAndSortingRepository<LsZFutelsz, Integer> {
    /*-----------------------------------------------------------------------------------------------*/
    @RestResource(exported=false)
    @Modifying
    @Query(value="DELETE FROM ls_z_futelsz f WHERE f.lako_id = ?1", nativeQuery=true)
    void deleteByLako(Integer integer);
    /*-----------------------------------------------------------------------------------------------*/ 
    LsZFutelsz findOneByLsTLako(LsTLako lsTLako);
}

Repository for the Type A entity

@RepositoryRestResource(collectionResourceRel = LsZFutelsz.VERB_FUTELSZHAVI, path = LsZFutelsz.VERB_FUTELSZHAVI)
public interface LsZFutelszHaviRepository extends PagingAndSortingRepository<LsZFutelszHavi, Integer> {

}

Entity Type A

@Entity
@Table(name="LS_Z_FUTELSZ_HAVI")
@NamedQuery(name="LsZFutelszHavi.findAll", query="SELECT l FROM LsZFutelszHavi l")
public class LsZFutelszHavi extends Audit implements Serializable {

    public static final String VERB_FUTELSZ  = "futelszamolasok";
    /*-----------------------------------------------------------------------------------------------*/
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name="GenFutelszHaviID", sequenceName="GEN_LS_Z_FUTELSZ_HAVI_ID", allocationSize= 1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="GenFutelszHaviID")
    @Column(name="HAVI_ELSZ_ID")
    private Integer haviElszId;

    @NotNull
    @Column(name="FIZ_KORR_OSSZ")
    private BigDecimal fizKorrOssz;

    @NotNull
    @Column(name="ORIG_KORR_OSSZ")
    private BigDecimal origKorrOssz;

    //uni-directional many-to-one association to LsFSzlafej
    @ManyToOne
    @JoinColumn(name="SZLA_ID")
    private LsFSzlafej lsFSzlafej;

    //uni-directional many-to-one association to LsTEvho
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name="EV", referencedColumnName="EV"),
        @JoinColumn(name="HO", referencedColumnName="HO")
        })
    private LsTEvho lsTEvho;

    //bi-directional many-to-one association to LsZFutelsz
    @ManyToOne
    @JoinColumn(name="ELSZ_ID")
    private LsZFutelsz lsZFutelsz;

    public LsZFutelszHavi() {
    }
    //[... setters getters ...]
}

Entity Type B

@Entity
@Table(name="LS_Z_FUTELSZ")
@NamedQuery(name="LsZFutelsz.findAll", query="SELECT l FROM LsZFutelsz l")
public class LsZFutelsz extends Audit implements Serializable {
    public static final String VERB_FUTELSZHAVI = "futelszhavi";
    /*-----------------------------------------------------------------------------------------------*/
    private static final long serialVersionUID = 1L;

    @Id
    @SequenceGenerator(name="GenFutelszID", sequenceName="GEN_LS_Z_FUTELSZ_ID", allocationSize= 1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="GenFutelszID")
    @Column(name="ELSZ_ID")
    private Integer elszId;

    @NotNull
    @Column(name="LEOLV_FOGY_GJ")
    private BigDecimal leolvFogyGj = BigDecimal.ZERO;

    @NotNull
    @Column(name="LEOLV_FOGY_OSSZ")
    private BigDecimal leolvFogyOssz = BigDecimal.ZERO;

    @NotNull
    @Column(name="ELOZ_SZEZ_OSSZ")
    private BigDecimal elozSzezOssz = BigDecimal.ZERO;

    @NotNull
    @Column(name="SZEZ_VEGEN_BEF_OSSZ")
    private BigDecimal szezVegenBefOssz = BigDecimal.ZERO;

    @NotNull
    @Column(name="SZOSZT_UTAN_FENNM")
    private BigDecimal szosztUtanFennm = BigDecimal.ZERO;

    @NotNull
    @Column(name="SZOSZTANDO_KULONB")
    private BigDecimal szosztandoKulonb = BigDecimal.ZERO;

    //uni-directional many-to-one association to LsTLakok
    @ManyToOne
    @JoinColumn(name="LAKO_ID")
    private LsTLako lsTLako;

    //bi-directional many-to-one association to LsZFutelszHavi
    @OneToMany(mappedBy="lsZFutelsz", cascade={CascadeType.REMOVE})
    private List<LsZFutelszHavi> lsZFutelszHaviTetelek;

    public LsZFutelsz() {
    }
    //[... setters getters ...]
}

The code works, The field is just always happen to be the default value.

After testing it with simple methods, the other entity got saved into the database as well. Then I put a breakpoint into the original code which only get breaked, if the new value for the entity is different than the default. The program converted everything without breaking at the breakpoint.

So, I looked up which database I converting, and see what the contents ar. To my surprise it was always zero, the default value.

It's awkward. I was so sure, I misunderstood something, and coded wrong.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM