Open
Description
Bug description
Fetching Entities(UserRole in ManyToOne association) described via jakarta.persistence.EmbeddedId in Spring Batch and with JpaCursorItemReader returns always a single value.
Example: User has two UserRoles with roleId1=1 and roleId2=4. In ItemProcessor I get always either roleId1 or roleI2 but not both.
Environment
Spring boot 3.1.3, Spring Batch 5.0.3, Hibernate-Core 6.2.7
Entities
@Entity
@Table( name = "user"
})
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User extends PersonExtendedImpl implements UserDetails, ToDto<UserDTO>, Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "User_ID")
private Integer id;
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@OneToMany(
mappedBy = "user",
cascade = CascadeType.ALL,
orphanRemoval = true)
private List<UserRole> userRoles = new ArrayList<UserRole>();
equals, hashcode, getter, setter
@Entity
@Table(name = "user_role",
uniqueConstraints={@UniqueConstraint(columnNames = {"User_ID", "Role_ID"})}
)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class UserRole implements Serializable {
@EmbeddedId
private UserRoleKey id;
@Setter(AccessLevel.NONE)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "User_ID", referencedColumnName = "User_ID", insertable=false, updatable=false)
private User user;
public UserRole(UserRoleKey id) {
this.id = id;
}
equals, hashcode, getter, setter
}
@Embeddable
public class UserRoleKey implements Serializable {
@Column(name = "User_ID")
private Integer userId;
@Column(name = "Role_ID")
private Integer roleId;
equals, hashcode, getter, setter
}
Steps to reproduce
@Bean
@Scope("prototype")
Step step( JobRepository jobRepository,
JpaCursorItemReader<User> userPrivilegeReader,
CustomerPrivilegeProcessor userPrivilegeProcessor,
PlatformTransactionManager userTransactionManager) throws Exception {
return new StepBuilder("customerPrivilegeStep", jobRepository)
.<User, User> chunk(10, userTransactionManager)
.reader( userPrivilegeReader )
.processor( userPrivilegeProcessor )
.writer(() -> System.out.println("NOT OKAY "))
.build();
}
This Step produces correct sql statement but just one UserRole fetched in List of userRoles.
SQL:
"""
SELECT u from User u
JOIN FETCH u.userRoles ur
WHERE u.expiresAt > CURRENT_TIMESTAMP
AND u.enabled = true
AND u.locked = false """
select u1_0.User_ID,u1_0.Auth_Type,u1_0.Birth_day,u1_0.Country_ID,u1_0.Email,u1_0.Enabled,u1_0.Expires_at,u1_0.First_Name,u1_0.Form_of_Address_ID,u1_0.Last_accessed_at,u1_0.Last_Name,u1_0.Last_updated_at,u1_0.Locked,u1_0.Locked_at,u1_0.Password,u1_0.Phone,u1_0.Registered_at,u1_0.Register_Type,u2_0.User_ID,u2_0.Role_ID,u1_0.Username
from user u1_0
join user_role u2_0 on u1_0.User_ID=u2_0.User_ID
where u1_0.Expires_at>current_timestamp(6)
and u1_0.Enabled=1 and u1_0.Locked=0
Important!
I could not reproduce the same issue in Spring Boot 3.1.3 and Spring MVC application environment!!!
Expected behavior
JpaItemReaders should fetch all associated Entities(UserRole's) into Collection of parent Entity(User).