0

I've searched for this exception before. But no solution worked for my problem.

I have two classes:

@Entity
@Table(name = "user")
public class User {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @OneToMany
    @JoinColumn(name = "tutor_id")
    private Set<Tutorium> tutoria;
}

and

@Entity
@Table(name = "tutorium")
public class Tutorium {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Colum(name = "tutor_id")
    private int tutor_id;
}

So the semantic is "One user could teach many tutoria".

But when I'm starting my application, I get the exception:

"Failed to create sessionFactory object.org.hibernate.AnnotationException: Use of @OneToMany or @ManyToMany targeting an unmapped class: model.User.tutoria[model.Tutorium]".

Does anyone know, how I can solve this problem?

Edit:

Trying to give you a small example of how I'm accessing the classes:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;

public class UserFilter {
    private static SessionFactory factory;

    public UserFilter() {
        try{factory = new Configuration().configure().addAnnotatedClass(User.class).buildSessionFactory();}
        catch(Exception e) {}
    }

    public Collection<User> getUser() {
        Session session = factory.openSession();
        Transaction t = null;
        try{
            t = session.beginTransaction();

            CriteriaBuilder cb = session.getEntityManagerFactory().getCriteriaBuilder();
            Join<User, Tutorium> tutoria = this.root().join("tutoria");
            CriteriaQuery output = cb.createQuery(User.class);
            output.groupBy(this.root().get("id"));

            TypedQuery q = session.getEntityManagerFactory().createEntityManager().createQuery(output);

            List users = q.getResultList();
            return users;
        }
        catch(Exception e) {}
        finally {
            session.close();
        }
    }
}

The part with the join and the groupBy-clause isn't tested yet. That was the function, I wanted to implement next. But before I was able to do this, the exception was thrown.

I hope, the example is mostly clear.

Stefan
  • 77
  • 1
  • 9
  • 2
    In your persitence.xml, do you use class path scanning for discovering classes? If not, is `Tutorium` listed? Or, happens sometimes, is the `@Entity` annotation in `Tutorium` not from the JPA package? – Brian Oct 27 '16 at 13:30
  • I havn't created a persistence.xml. Because the tutorial at [link](https://www.tutorialspoint.com/hibernate/) said, that if you use annotations you won't need a xml-configfile... :O – Stefan Oct 27 '16 at 13:46
  • Besides the fact that your mapping looks wrong for what you want, as said on the posted answers, I think this is not the cause of your problem. Take a look at http://stackoverflow.com/questions/4956855/hibernate-problem-use-of-onetomany-or-manytomany-targeting-an-unmapped-clas – Leonardo Cruz Oct 27 '16 at 14:04
  • @Stefan, from what I understand (https://www.tutorialspoint.com/hibernate/hibernate_annotations.htm) they are referring the mapping information *inside* each entity class. I'm curious how you are trying to work with your classes. Could you post a small snippet on that? I want to know if you are going the "Hibernate" or the "JPA" way. – Brian Oct 27 '16 at 14:47
  • "persistence.xml" is mandatory in JPA so your reference is wrong. Find any decent JPA tutorial – Neil Stockton Oct 27 '16 at 16:03
  • @NeilStockton, fyi: Though you are right regarding the fact that a persistence.xml is mandatory in a true JPA environment, most frameworks simply translate it to their own vendor specific configuration mechanism which needn't be static (that is file based). Spring for example enables you to initialize JPA via Hibernate by using an annotation based Spring configuration. And this is what I'm trying to figure out here. How is he initializing his environment? – Brian Oct 27 '16 at 16:20
  • Sorry for my late answer. I posted the access to the entity-classes in my original post as the edit. Maybe I really mixed too much Hibernate and JPA together. But I had to start with Hibernate at first and while my work with the program, my teamleader decided to use JPA instead. In each case I'll look for a JPA tutorial and try to figure out, if I must use a "persistence.xml"-file. – Stefan Oct 28 '16 at 22:31
  • Two things come to mind when looking at your code. Firstly, you are right. It sure looks like you started with Hibernate and then switched to JPA. Not a big deal, but I recommend either going for the Hibernate or the JPA way. Try to not mix both, because it can be confusing. It helps in the long run. Secondly, take a look at @Douglas's answer. It should help fixing your problem. Have fun. – Brian Oct 30 '16 at 14:03

2 Answers2

4

In this line:

try{factory = new Configuration().configure().addAnnotatedClass(User.class).buildSessionFactory();}

You are telling Hibernate that User is a mapped class. That is the one and only class you tell it about, so that's the one and only class that it examines for mapping info. If you want it to also treat Tutorium as a mapped class, you need to tell it about that too. Simply adding .addAnnotatedClass(Tutorium.class) into the configuration call chain should do it.

Douglas
  • 5,017
  • 1
  • 14
  • 28
-1

You need to map reverse way e.g. if User is parent table and Tutorium is child table you will put mappedBy attribute in User class and for child table Tutorium you will use @JoinColumn which will refer to foreign key column in parent class. See code below

@Entity
@Table(name = "user")
public class User {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @OneToMany(mappedBy = "user")
    private Set<Tutorium> tutoria;
}



@Entity
@Table(name = "tutorium")
public class Tutorium {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @ManyToOne
    @JoinColumn(name = "id")
    private User user;
}
Panda
  • 6,955
  • 6
  • 40
  • 55
M. Atif Riaz
  • 492
  • 1
  • 9
  • 22
  • Tested it actually. But got the same exception... But thank you for your help – Stefan Oct 27 '16 at 13:50
  • Using a bidirectional mapping is no requirement for using `@OneToMany`. – Brian Oct 27 '16 at 14:28
  • @Brian This is an example I am quoting from Entity generated by Jboss Tools. You can use unidirectional mapping but there is nothing wrong using bidirectional relationship – M. Atif Riaz Oct 27 '16 at 18:24
  • @M.AtifRiaz Yes, there's nothing wrong with using bidirectional mappings over unidirectional mappings, apart from the code overhead if one does not need it. It simply doesn't solve the problem and just by looking at the error in the question, one can tell. That is why I voted your answer down and posted the reason for it in my previous comment in compliance with the etiquette on Stackoverflow. – Brian Oct 27 '16 at 18:32