Sairam Cherupally
Sairam Cherupally

Reputation: 341

why is detached entity treated as transient?

I am using Hibernate as JPA provider. I have fetched account entity from the database and detached it. So, the account entity must now be in a detached state. Now when I try to persist the detached entity, I was expecting it to fail, as entitymananger.persist method works only on transient and managed entities. But it is running INSERT query on database.

Further debugging the entitymananger.persist implementation, I found that it is considering account entity as TRANSIENT. I put the breakpoint here to see entity state,

The code used for testing:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MainApplication.class)
public class HibernateTest {

    @PersistenceContext
    private EntityManager entityManager;

    @Test
    @Transactional
    @Commit
    public void testDetached() {
        Account account = entityManager.find(Account.class, 1); // account is now managed entity
        entityManager.detach(account); // detach the account entity
        entityManager.persist(account);// entityManager is treating account as transient object and ran INSERT query on the database

    }

}

Adding the Account class

@Entity
@lombok.Data
@Table(name = "account")
class Account {

    @Id
    @Column(name = "userid")
    private int userid;

    @Column(name = "balance")
    private int balance;

}

My questions are:

  1. Why is entitymanager.persist considering detached entity as transient ?
  2. I tried understanding Hibernate determination of whether an entity is transient or detached (code). the logic is complex and couldn't internalize why it is done the way it is done.

Please let me know if you need any further details. Thanks.

Upvotes: 2

Views: 272

Answers (1)

Bon
Bon

Reputation: 250

An entity is considered DETACHED if :

1. ID is not null (otherwise it is transient)
2. It is not managed
3. It has not been removed

Im not sure how you are assigning the ID property, but i guess the problem is somewhere around there.

Leave the ID generation to hibernate:

    @Id
    @GeneratedValue  <<<<<<<
    @Column(name = "userid")
    private int userid;

That should fail the test.

Upvotes: 3

Related Questions