JdbcTemplate + entityManager wspolpraca.

0

Witam, sytuacja wyglada tak, ze mam encje Account ktora posiada wszystkie dane z tabeli kont oprocz hasla. Haslo chce zapisywac za pomoca jdbcTemplate i tu pojawia sie maly problem.

package pl.benq.enrollment.service.imp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import pl.benq.enrollment.model.Account;
import pl.benq.enrollment.repository.AccountPasswordRepository;
import pl.benq.enrollment.repository.AccountRepository;
import pl.benq.enrollment.service.RegistrationService;

@Service("registrationService")
@Transactional
public class RegistrationServiceImp implements RegistrationService{
	
	@Autowired AccountRepository accountRepository;
	@Autowired AccountPasswordRepository passwordRepository;

	@Override
	public Boolean isLoginAvaiable(String login) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void createAccount(Account account, String password) {
		accountRepository.save(account);
		passwordRepository.updatePasswordByUsername(account.getLogin(), password);		
	}
}

Metoda createAccount nie dziala jak nalezy, poniewaz nie zostaje zapisane haslo. Wyglada to tak jakby wywolalo sie save z repository przy czym oddalo sterowanie do createAccount zanim encja zostala utrwalona i zaczyna sie wykonywac updatePassword... Jak taki problem rozwiazac i dlaczego dokladnie tak sie dzieje?

0

Hej, jak wygląda metoda save i jak wygląda updatePasswordByUsername?

0
@Override
	public void updatePasswordByUsername(String username,String password) {				
		jdbcTemplate.update(UPDATE_PASSWORD_SQL,password,username);			
	}

a save to JpaRepository ze Spring data

@Edit Ok, w teori to "You should be aware though that JPA caches the queries and executes all of them at the end of a transaction. So if you want to persist some data inside a transaction with JPA and then retrieve the data with JDBC, it will not work without explicitely flushing the JPA's persistence context before you attempt to retreive it with JDBC code." Tylko teraz jak sie z tym uporac;p

0

Moja pierwsza myśl jest taka, że @Transactional powinien być przed tymi metodami:

@Override
@Transactional
    public void updatePasswordByUsername(String username,String password) {                
        jdbcTemplate.update(UPDATE_PASSWORD_SQL,password,username);            
    } 

W ten spsób masz osobne trasakcje dla obyudwu wywołań i powinieneś mieć pewność, że save wykona się przed update i zakończy transakcje zanim wejście do update. Ale to tak na oko.

0

Powiem szczerze, ze myslalem na przeniesienie do osobnych transakcji dwoch ale jezeli by istnial sposob zeby to w jednej zalatwic to bym go preferowal;)

0

Obydwa repozytoria odwołują się do tej samej bazy, jak rozumiem?

0

Problem rozwiazany. Jakby ktos na cos takiego sie natrafil to trzeba zmodyfikowac beana transactionManager dodajac odpowiedni jpaDialect

This transaction manager also supports direct DataSource access within a transaction (i.e. plain JDBC code working with the same DataSource). This allows for mixing services which access JPA and services which use plain JDBC (without being aware of JPA)! Application code needs to stick to the same simple Connection lookup pattern as with DataSourceTransactionManager (i.e. DataSourceUtils.getConnection(javax.sql.DataSource) or going through a TransactionAwareDataSourceProxy). Note that this requires a vendor-specific JpaDialect to be configured.

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
		p:entityManagerFactory-ref="entityManagerFactory">
		<property name="jpaDialect">
			<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
		</property>
	</bean>

i uzycia metody saveAndFlush co spowoduje natychmiastowe wypchniecie zmian do db zamiast cachowac wszystko i czekac na koniec transakcji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1