Pracede
Pracede

Reputation: 4371

Hibernate 4 : Why i am getting the AnnotationException : Unknown mappedBy?

I am trying to generate sql schema from Hibernate Entities. Here are my entities :

Student entity

@Entity
@Table(name = "address") 
public class Address {

     @Id
     private long id;  

     @Column(name = "address")  
     private String address;  

     @Column(name = "city")  
     private String city;  

     @Column(name = "state")  
     private String state;  

     @Column(name = "country")  
     private String country;  

     @OneToOne (mappedBy="student")  
     private Student student;  

     public Address(){  

     }  

     public Address(String address, String city, String state,  
       String country) {  
      this.address = address;  
      this.city = city;  
      this.state = state;  
      this.country = country;  
     }  

Address entity

@Entity  
@Table(name = "student") 
public class Student {

    @Id
    @GeneratedValue
    @Column(name = "student_id")  
    private long id;  

    @Column(name = "first_name")  
    private String firstName;  

    @Column(name = "last_name")  
    private String lastName;  

    @Column(name = "email")  
    private String email;  

    @Column(name = "phone")  
    private String phone;  

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="ADDRESS_ID")
    private Address address;  

    public Student(){  

    }  

    public Student(String firstName, String lastName, String email, String phone) {  
     this.firstName = firstName;  
     this.lastName = lastName;  
     this.phone = phone;  
     this.email = email;  
    }  

+ getters and setters   

}

Generation schema class

    public class SchemaGenerator {


        private Configuration cfg;

        @SuppressWarnings("rawtypes")
        public SchemaGenerator(String packageName) throws Exception {
            cfg = new Configuration();
            cfg.setProperty("hibernate.hbm2ddl.auto", "create");

            for (Class clazz : getClasses(packageName)) {
                cfg.addAnnotatedClass(clazz);
            }
        }

        public static void main(String[] args) throws Exception {
            //final String packageName = args[0];
            final String packageName ="com.startup.app.models.entities";
            SchemaGenerator gen = new SchemaGenerator(packageName);
           // final String directory = args[1];
            final String directory = "E:\\Informatique\\workspace\\startup\\src\\main\\resources\\sql\\";
            gen.generate(Dialect.MYSQL, directory);
            gen.generate(Dialect.POSTGRESQL, directory);
        }



    private List<Class> getClasses(String packageName) throws Exception {
        File directory = null;
        try {
            ClassLoader cld = getClassLoader();
            URL resource = getResource(packageName, cld);
            directory = new File(resource.getFile());
        } catch (NullPointerException ex) {
            throw new ClassNotFoundException(packageName + " (" + directory
                    + ") does not appear to be a valid package");
        }
        return collectClasses(packageName, directory);
    }

    private ClassLoader getClassLoader() throws ClassNotFoundException {
        ClassLoader cld = Thread.currentThread().getContextClassLoader();
        if (cld == null) {
            throw new ClassNotFoundException("Can't get class loader.");
        }
        return cld;
    }

    private URL getResource(String packageName, ClassLoader cld) throws ClassNotFoundException {
        String path = packageName.replace('.', '/');
        URL resource = cld.getResource(path);
        if (resource == null) {
            throw new ClassNotFoundException("No resource for " + path);
        }
        return resource;
    }

    private List<Class> collectClasses(String packageName, File directory) throws ClassNotFoundException {
        List<Class> classes = new ArrayList<Class>();
        if (directory.exists()) {
            String[] files = directory.list();
            for (String file : files) {
                if (file.endsWith(".class")) {
                    // removes the .class extension
                    classes.add(Class.forName(packageName + '.'
                            + file.substring(0, file.length() - 6)));
                }
            }
        } else {
            throw new ClassNotFoundException(packageName
                    + " is not a valid package");
        }
        return classes;
    }

    private void generate(Dialect dialect, String directory) {
        cfg.setProperty("hibernate.dialect", dialect.getDialectClass());
        SchemaExport export = new SchemaExport(cfg);
        export.setDelimiter(";");
        export.setOutputFile(directory + "ddl_" + dialect.name().toLowerCase() + ".sql");
        export.setFormat(true);
        export.execute(true, false, false, false);
    }


    private static enum Dialect {
        MYSQL("org.hibernate.dialect.MySQLDialect"),
        POSTGRESQL("org.hibernate.dialect.PostgreSQLDialect");

        private String dialectClass;

        private Dialect(String dialectClass) {
            this.dialectClass = dialectClass;
        }

        public String getDialectClass() {
            return dialectClass;
        }
    }


 }

But i don't understand why when i try to generate schema i have the following error :

INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
Exception in thread "main" org.hibernate.AnnotationException: Unknown mappedBy in: com.davy.app.domain.onetoone.one.entities.Address.student, referenced property unknown: com.davy.app.domain.onetoone.one.entities.Student.student
    at org.hibernate.cfg.OneToOneSecondPass.doSecondPass(OneToOneSecondPass.java:158)
    at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1586)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1359)
    at org.hibernate.cfg.Configuration.generateDropSchemaScript(Configuration.java:927)
    at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.java:189)
    at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.java:157)
    at com.davy.app.domain.utils.SchemaGenerator.generate(SchemaGenerator.java:103)
    at com.davy.app.domain.utils.SchemaGenerator.main(SchemaGenerator.java:36)

Upvotes: 0

Views: 892

Answers (3)

saravanakumar
saravanakumar

Reputation: 1777

You are trying with same table name "student" change

    @Table(name = "student") 

to another name somthing like

    @Table(name = "address") 

at Class Address.

Upvotes: 1

Pracede
Pracede

Reputation: 4371

I've found the solution. The problem was about ( class Adress) :

 @OneToOne (mappedBy="student")  
 private Student student;

Avec change it to

 @OneToOne 
private Student student;

The the entity Student, i've add mappedBy:

 @OneToOne(cascade = CascadeType.ALL,mappedBy="student")
    @JoinColumn(name="ADDRESS_ID")
    private Address address;  

Upvotes: 0

Thomas
Thomas

Reputation: 88747

mappedBy defines the name of the property that maps the association on the other side. In your case it wouldn't be student but address, e.g.

public class Address {
  @OneToOne (mappedBy="address")  //<- not "student"
  private Student student; 
}  

public class Student {
  @OneToOne(cascade = CascadeType.ALL)
  @JoinColumn(name="ADDRESS_ID")
  private Address address; //<- this maps the association and thus is the value for the corresponding mappedBy
}  

Besides that, there are other mapping errors as well, e.g. the same table name being used as saran pointed out.

Upvotes: 0

Related Questions