Hi, ich sitze gerade an einer Aufgabe für die Uni und kann daher das Datenmodell nicht ändern. Das Datenmodell sieht so aus:
Das consistsOf
der TaskForce macht Probleme. Ich bekomme folgende Exception: javax.persistence.PersistenceException: org.hibernate.PropertyAccessException: could not get a field value by reflection getter of dst.ass1.jpa.model.impl.TaskForce.id
.
Meine Klasse sieht so aus:
@Entity
public class TaskForce implements ITaskForce {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(unique = true)
private String name;
private Date lastMeeting;
private Date nextMeeting;
@ManyToMany(mappedBy = "partOf", targetEntity = TaskForce.class)
private List<ITaskForce> composedOf = new LinkedList<ITaskForce>();
@ManyToMany(targetEntity = TaskForce.class)
@JoinTable(name="composed_of")
private List<ITaskForce> partOf = new LinkedList<ITaskForce>();
@OneToMany(targetEntity = TaskWorker.class)
private List<ITaskWorker> taskWorkers = new LinkedList<ITaskWorker>();
@ManyToOne(targetEntity = Expert.class)
private IExpert expert;
@ManyToOne(targetEntity = WorkPlatform.class)
private IWorkPlatform workPlatform;
@Override
public Long getId() {
return this.id;
}
@Override
public void setId(Long id) {
this.id = id;
}
// restlichen getter/setter
}
Einer der Testfälle der das auslöst sieht so aus:
@SuppressWarnings("unchecked")
@Test
public void testNamedQueryFindUsersWithActiveMembership2() {
EntityTransaction tx = em.getTransaction();
try {
tx.begin();
Query query = em
.createNamedQuery(Constants.Q_USERSWITHACTIVEMEMBERSHIP);
query.setParameter("name", "foobar");
query.setParameter("minNr", 2L);
List<IUser> result = (List<IUser>) query.getResultList();
assertNotNull(result);
assertEquals(0, result.size());
} catch (Exception e) {
fail(ExceptionUtils.getMessage(e));
} finally {
tx.rollback();
}
}
Hat einer eine Ahnung was es hier hat?
Im Mapping keine Fehler zu erkennen. Kannst Du mal den Querystring Constants.Q_USERSWITHACTIVEMEMBERSHIP posten?
Hi, der Name wird dich nicht weiter interessieren. Aber ich kann gerne das NamedQuery (samt dazugehöriger Entity) posten:
@NamedQueries({
@NamedQuery(name = Constants.Q_USERSWITHACTIVEMEMBERSHIP, query =
" SELECT mem.user "
+ "FROM Membership mem "
+ "WHERE mem.workPlatform.name = :name AND "
+ "(SELECT COUNT(tsk) FROM Task tsk "
+ " JOIN tsk.taskProcessing tskproc "
+ " JOIN tskproc.taskWorkers tskwrkr"
+ " JOIN tskwrkr.taskForce tskfrc "
+ " JOIN tskfrc.workPlatform wrkplat "
+ " WHERE wrkplat.name = :name"
+ " AND tsk.user = mem.user) >= :minNr"),
@NamedQuery(name = Constants.Q_MOSTACTIVEUSER, query =
" SELECT user " +
" FROM User user " +
" WHERE user.tasks.size = (SELECT MAX(tmpU.tasks.size) FROM User tmpU) " +
" AND user.tasks.size > 0")
})
@Entity
public class User extends Person implements IUser {
private String username;
@Column(columnDefinition = "BINARY(16)")
@Index(name = "IDX_PASSWORD")
private byte[] password;
@Column(unique = true)
private String accountNo;
@Column(unique = true)
private String bankCode;
@OneToMany(targetEntity = Task.class)
private List<ITask> tasks = new LinkedList<ITask>();
@OneToMany(targetEntity = Membership.class)
private List<IMembership> memberships = new LinkedList<IMembership>();
// getter/setter
}
Es ist generell so, dass die TaskForce-Klasse an mehreren Stellen gebraucht wird. Der Test oben ist nur exemplarisch. Es schlagen 39 Tests mit dieser Exception fehl. Hier noch die TaskProcessing Entity:
@Entity
public class TaskProcessing implements ITaskProcessing {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private Date start;
private Date end;
@Enumerated(EnumType.STRING)
private TaskStatus status;
@ManyToMany(targetEntity = TaskWorker.class)
@JoinTable(name="PROCESSING_TASKWORKER",
joinColumns={@JoinColumn(name="TASKPROCESSINGS_ID", referencedColumnName="ID")},
inverseJoinColumns={@JoinColumn(name="TASKWORKERS_ID", referencedColumnName="ID")})
private List<ITaskWorker> taskWorkers;
@OneToOne(targetEntity = Task.class)
private ITask task;
// getter/setter
}
Und der TaskWorker:
@Entity
@EntityListeners({ WorkerListener.class })
public class TaskWorker implements ITaskWorker {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(unique = true)
@Size(min=5, max = 25)
private String name;
@WorkUnitCapacity(min=4, max=8)
private Integer workUnitCapacity;
@Size(min=12)
@Pattern(regexp = "[A-Z]{3}-[A-Z]@[0-9]+")
private String location;
@Past
private Date joinedDate;
@Past
private Date lastTraining;
private List<ITaskProcessing> processings = new LinkedList<ITaskProcessing>();
private ITaskForce taskForce;
// getter/setter
WorkUnitCapacity ist nur eine custom Validation. Kannst du ignorieren.