0

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;  
     }  
  • getters and setters

    }

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)

3 Answers 3

1

You are trying with same table name "student" change

    @Table(name = "student") 

to another name somthing like

    @Table(name = "address") 

at Class Address.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes it was a copy error. I did not pay attention when a paste code. Thanks
0

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.

Comments

0

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;  

2 Comments

This would map the student to some student-id column in the address table instead of the address to column ADDRESS_ID in the student table.
You're right but in my case i think @JoinColumn is not useful

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.