Ассоциированный объект не сохраняется в транзакции
Я довольно новичок в структурах сущностей и не понимаю, почему моя сущность не сохраняется правильно.
редактировать:
Я постараюсь выпустить этот тестовый код в ближайшее время и посмотреть, работает ли он:
@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);
}
Я пытаюсь преобразовать из старой базы данных DBASE в базу данных Firebird. В базе данных Firebird есть таблицы, сопоставленные сущностями. Я читаю таблицу DBASE, а затем конвертирую ее построчно.
Я использую @Transactional, чтобы либо сохранить все преобразованные объекты таблицы DBASE, либо не сохранять ни одного.
Мне удалось правильно преобразовать каждую таблицу в новую базу данных, кроме одной.
В других таблицах мне нужно было сохранить только одну сущность для каждой записи, и мне не пришлось изменять сущности другого типа. Мне обычно приходилось создавать объект типа X, подключать его к объекту типа Y, а затем сохранять. Для сохранения я использую репозиторий для сущности (org.springframework.data.repository.PagingAndSortingRepository, если это имеет значение)
В этой конкретной таблице DBASE мне нужно создать одну сущность типа A, подключить ее к сущности типа B, изменить сущность типа B, а затем сохранить. Проблема в том, что модификация сущности типа B не сохраняется в таблице Firebird. Опять же, я использую хранилище, чтобы сохранить сущность.
Чтобы получить сущность типа B, я использую метод репозитория:
LsZFutelsz findOneByLsTLako(LsTLako lsTLako);
Я догадывался, что, возможно, если я сохраню этот объект типа B с собственным репозиторием, он будет корректно изменен в базе данных. Это не помогло.
Скажите, пожалуйста, нужна ли дополнительная информация.
Я копирую свой слегка измененный код здесь (убрал некоторые записи, добавил несколько комментариев). LsZFutelszHavi - это EntityClass типа A, LsZFutelsz - это EntityClass типа B.
Конвертер абстрактный класс. Он наследуется для каждой таблицы DBASE
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);
}
Дочерний класс, который внедряет метод konvertToEntity.
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;
}
}
Репозиторий для сущности типа B
@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);
}
Хранилище для объекта типа A
@RepositoryRestResource(collectionResourceRel = LsZFutelsz.VERB_FUTELSZHAVI, path = LsZFutelsz.VERB_FUTELSZHAVI)
public interface LsZFutelszHaviRepository extends PagingAndSortingRepository<LsZFutelszHavi, Integer> {
}
Тип объекта А
@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 ...]
}
Тип объекта 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 ...]
}
1 ответ
Код работает, поле просто всегда оказывается значением по умолчанию.
После тестирования простыми методами, другая сущность также была сохранена в базе данных. Затем я помещаю точку останова в исходный код, который разбивается, только если новое значение для сущности отличается от значения по умолчанию. Программа конвертирует все без прерывания в точке останова.
Итак, я посмотрел, какую базу данных я конвертировал, и увидел, какое содержимое есть. К моему удивлению, это всегда было ноль, значение по умолчанию.
Это неловко. Я был так уверен, я что-то не так понял и неправильно написал.