Spring-Hibernate persist не приводит к вставке - PullRequest
6 голосов
/ 02 марта 2011

Я пытаюсь реализовать простой DAO.У меня есть Dao:

@Repository("iUserDao")
@Transactional(readOnly = true)
public class UserDao implements IUserDao {
    private EntityManager entityManager;

    @PersistenceContext
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public User getById(int id) {
        return entityManager.find(User.class, id);
    }

    @Override
    public boolean save(User user) {
        entityManager.persist(user);
        entityManager.flush();
        return true;
    }

    @Override
    public boolean update(User user) {
        entityManager.merge(user);
        entityManager.flush();
        return true;
    }

    @Override
    public boolean delete(User user) {
        user = entityManager.getReference(User.class, user.getId());
        if (user == null)
            return false;
        entityManager.remove(user);
        entityManager.flush();
        return true;
    }

И сущность:

@Entity
@Table(name = "users")
public class User {
    private int id;
    private Date creationDate;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public int getId() {
        return id;
    }

    public User() {
    }

    public User(Date creationDate) {
        this.creationDate = creationDate;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Date getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Date creationDate) {
        this.creationDate = creationDate;
    }
}

Вот appContext.xml: `

<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
      p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaAdapter"
      p:persistenceUnitName="test">
    <property name="loadTimeWeaver">
        <bean
                class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
      p:entityManagerFactory-ref="entityManagerFactory"/>
<bean id="jpaAdapter"
      class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
      p:database="MYSQL" p:showSql="true"/>

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<tx:annotation-driven/>`

Если я не позвоню flush() после persist() или merge() вставка не выполнена.Это почему?Если я удаляю @Transactional, я получаю сообщение об ошибке «транзакция не выполняется» при очистке, но при удалении очистки ничего не вставляется в БД.

Ответы [ 2 ]

10 голосов
/ 02 марта 2011

Это работает так, потому что вы пометили транзакцию как только для чтения с @Transactional(readOnly = true).

Как видите, это не делает ваши транзакции доступными только для чтения, так как вы можете сохранить изменения, вызвав flush() вручную.Однако он отключает автоматическую очистку в конце транзакции, поэтому изменения не сохраняются без ручной очистки.

Вам необходимо либо удалить readOnly из аннотации на уровне класса, либо переопределить ее для не только для чтенияметоды с аннотациями уровня метода:

@Override
@Transactional(readOnly = false)
public boolean save(User user) { ... }

Также обратите внимание, что разграничение транзакций обычно применяется к методам уровня обслуживания, а не к методам DAO.В частности, при написании методов DAO вы на самом деле не знаете, какие транзакции должны быть только для чтения, а какие нет.Эта информация доступна только при разработке сервисного уровня, как вы можете видеть в следующем примере:

public class UserService {
    @Autowired UserDAO dao;

    @Transactional(readOnly = true) 
    public User getUserById(int id) {
        return dao.getById(id); // getById() can participate in effectively read-only transaction
    }

    @Transactional
    public void changeUserName(int id, String newName) {
        User u = dao.getById(id); // Or not
        u.setName(newName); // Change will be flushed at the end of transaction
    }
}
1 голос
/ 02 марта 2011

Попробуйте установить требуемое распространение транзакций и удалите все flush(): -

@Repository("iUserDao")
@Transactional(propagation=Propagation.REQUIRED)
public class UserDao implements IUserDao {
   ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...