@Columns not allowed at @OneToOne

Mein Programm benutzt Hibernate 4.x. Meine Klasse sieht wie folgt aus

@Entity
@Table(name="user")
public class User { 
	     @Id
	     @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_gen")
	     @SequenceGenerator(name = "user_gen", sequenceName = "user_id_seq")
	    private Integer id;
	    @Column(name="created_by", nullable = false)
	    @OneToOne
	    private User    created_by;
	    @Column(name="created_at", nullable = false)
	    @Type(type="timestamp")
	    private Date    created_at;
            ...
		    
	    public int getId() {
	        return id;
	    }
	 
	    public void setId(int id) {
	        this.id = id;
	    }

	    public User getCreatedBy() {
			return created_by;
		}
	    
	    public void setCreatedBy(User user) {
			this.created_by = created_by;
		}
		
	   public Date getCreatedAt() {
			return created_at;
		}
		
	   public void setCreatedAt(Date created_at) {
			this.created_at = created_at;
		}
}

Beim Compilieren wird mir aber gemeldet


Caused by: org.hibernate.AnnotationException: @Column(s) not allowed on a @OneToOne property: skunitz.myprj.User.created_by

Kann mir einer verraten wie es korrekt angegeben werden müsst?

@joincolumn ist das, was du suchst

Ich habe immer noch Probleme. Meine Klasse sieht jetzt wie folgt aus

package skunitz.myprj;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

import org.hibernate.annotations.Type;
	 
@Entity
@Table(name="user")
public class User { 
	    @Id
	    @GeneratedValue(strategy = GenerationType.IDENTITY)
		@Column(name = "id", unique = true, nullable = false)	    
	    private int id;
	    @Column(name="created_by")
	    @OneToOne(fetch = FetchType.LAZY)
	    @JoinColumn 
	    private User    created_by;	    
	    @Column(name="created_at", nullable = false)
	    @Type(type="timestamp")
	    private Date    created_at;
	    @Column(name="blocked", nullable = false)
	    private boolean blocked;
	    @Column(name="deleted", nullable = false)
	    private boolean deleted;
	    @Column(name="activcode", unique = true, nullable = false)
	    private String  activcode;
	    @Column(name="firstname")
	    private String  firstname;
	    @Column(name="lastname")
	    private String  lastname;
	    @Column(name="email", unique = true, nullable = false)
	    private String  email;
	    @Column(name="password", nullable = false)
	    private String  password;
		    
	    public int getId() {
	        return id;
	    }
	 
	    public void setId(int id) {
	        this.id = id;
	    }

	    public User getCreatedBy() {
			return created_by;
		}
	    
		public void setCreatedBy(User user) {
			this.created_by = user;
		}

		public Date getCreatedAt() {
			return created_at;
		}
		
		public void setCreatedAt(Date created_at) {
			this.created_at = created_at;
		}

		public boolean isBlocked() {
			return blocked;
		}

		public void setBlocked(boolean blocked) {
			this.blocked = blocked;
		}
		
		public boolean isDeleted() {
			return deleted;
		}
		
		public void setDeleted(boolean deleted) {
			this.deleted = deleted;
		}
		
		public String getActivcode() {
			return activcode;
		}
		
		public void setActivcode(String activcode) {
			this.activcode = activcode;
		}

	    public String getFirstname() {
	        return firstname;
	    }
	 
	    public void setFirstname(String firstname) {
	        this.firstname = firstname;
	    }

	    public String getLastname() {
			return lastname;
		}
	    
		public void setLastname(String lastname) {
			this.lastname = lastname;
		}
		
		public String getEmail() {
			return email;
		}
		
		public void setEmail(String email) {
			this.email = email;
		}
		
		public String getPassword() {
			return password;
		}
		
		public void setPassword(String password) {
			this.password = password;
		}

	 
	    @Override
		public String toString() {
			return "User [id=" + id + ", created_by=" + created_by
					+ ", created_at=" + created_at + ", blocked=" + blocked
					+ ", deleted=" + deleted + ", activcode=" + activcode
					+ ", firstname=" + firstname + ", lastname=" + lastname
					+ ", email=" + email + ", password=" + password + "]";
		}
}

Die Datentabelle sieht wie folgt aus


CREATE TABLE IF NOT EXISTS `user` (
  `id` int(11) NOT NULL,
  `created_by` int(11) DEFAULT NULL,
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `blocked` tinyint(1) NOT NULL DEFAULT '0',
  `deleted` tinyint(1) NOT NULL DEFAULT '0',
  `activcode` varchar(255) NOT NULL,
  `firstname` varchar(255) NOT NULL,
  `lastname` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `activcode` (`activcode`),
  UNIQUE KEY `idx_login` (`email`,`password`),
  UNIQUE KEY `email` (`email`),
  KEY `blocked` (`blocked`),
  KEY `deleted` (`deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Die gesamte Fehlermeldung lautet


Jul 25, 2014 8:26:31 PM org.apache.catalina.core.AprLifecycleListener init
INFORMATION: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Program Files\Java\jre8\bin;C:\Windows\Sun\Java\bin;C:\Windows\system32;C:\Windows;C:/Program Files/Java/jre8/bin/client;C:/Program Files/Java/jre8/bin;C:/Program Files/Java/jre8/lib/i386;F:\Programme\maven\bin;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files\Intel\Intel(R) Management Engine Components\DAL;C:\Program Files\Intel\Intel(R) Management Engine Components\IPT;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Java\jdk1.8.0_05\bin;F:\Programme\eclipse-jee-juno-SR1-win32\eclipse;;.
Jul 25, 2014 8:26:31 PM org.apache.tomcat.util.digester.SetPropertiesRule begin
WARNUNG: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:myPrj' did not find a matching property.
Jul 25, 2014 8:26:32 PM org.apache.coyote.AbstractProtocol init
INFORMATION: Initializing ProtocolHandler ["http-bio-8080"]
Jul 25, 2014 8:26:32 PM org.apache.coyote.AbstractProtocol init
INFORMATION: Initializing ProtocolHandler ["ajp-bio-8009"]
Jul 25, 2014 8:26:32 PM org.apache.catalina.startup.Catalina load
INFORMATION: Initialization processed in 986 ms
Jul 25, 2014 8:26:32 PM org.apache.catalina.core.StandardService startInternal
INFORMATION: Starting service Catalina
Jul 25, 2014 8:26:32 PM org.apache.catalina.core.StandardEngine startInternal
INFORMATION: Starting Servlet Engine: Apache Tomcat/7.0.47
Jul 25, 2014 8:26:33 PM org.apache.catalina.util.SessionIdGenerator createSecureRandom
INFORMATION: Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [172] milliseconds.
Jul 25, 2014 8:26:33 PM org.apache.catalina.loader.WebappClassLoader validateJarFile
INFORMATION: validateJarFile(F:\projekte\java\eclipse2\.metadata\.plugins\org.eclipse.wst.server.core	mp0\wtpwebapps\myPrj\WEB-INF\lib\javax.servlet-api-3.1-b09.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
Jul 25, 2014 8:26:38 PM org.apache.catalina.core.ApplicationContext log
INFORMATION: No Spring WebApplicationInitializer types detected on classpath
Jul 25, 2014 8:26:38 PM org.apache.catalina.core.ApplicationContext log
INFORMATION: Initializing Spring root WebApplicationContext
log4j:WARN No appenders could be found for logger (org.springframework.web.context.ContextLoader).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Jul 25, 2014 8:26:41 PM org.apache.catalina.core.StandardContext listenerStart
SCHWERWIEGEND: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'UserService' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean 'UserDAO' while setting bean property 'userDAO'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'UserDAO' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean 'SessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'SessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: @Column(s) not allowed on a @OneToOne property: skunitz.myprj.User.created_by
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:336)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1456)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:703)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
	at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:403)
	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)
	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106)
	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4939)
	at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559)
	at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549)
	at java.util.concurrent.FutureTask.run(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.lang.Thread.run(Unknown Source)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'UserDAO' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean 'SessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'SessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: @Column(s) not allowed on a @OneToOne property: skunitz.myprj.User.created_by
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:336)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1456)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
	... 24 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'SessionFactory' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: @Column(s) not allowed on a @OneToOne property: skunitz.myprj.User.created_by
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
	... 34 more
Caused by: org.hibernate.AnnotationException: @Column(s) not allowed on a @OneToOne property: skunitz.myprj.User.created_by
	at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1812)
	at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:963)
	at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:796)
	at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3788)
	at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3742)
	at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1410)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1844)
	at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1928)
	at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:343)
	at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:431)
	at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:416)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
	... 41 more

Jul 25, 2014 8:26:41 PM com.sun.faces.config.ConfigureListener contextInitialized
INFORMATION: Mojarra 2.2.2 ( 20130809-1625 https://svn.java.net/svn/mojarra~svn/tags/2.2.2@12376) für Kontext '/myPrj' wird initialisiert.
Jul 25, 2014 8:26:41 PM com.sun.faces.spi.InjectionProviderFactory createInstance
INFORMATION: JSF1048: PostConstruct/PreDestroy-Annotationen vorhanden.  Verwaltete Bean-Methoden, die mit diesen Annotationen markiert sind, lassen die entsprechenden Annotationen verarbeiten.
Jul 25, 2014 8:26:43 PM com.sun.faces.config.ConfigureListener$WebConfigResourceMonitor$Monitor <init>
INFORMATION: Monitoring jndi:/localhost/myPrj/WEB-INF/faces-config.xml for modifications
Jul 25, 2014 8:26:43 PM org.primefaces.webapp.PostConstructApplicationEventListener processEvent
INFORMATION: Running on PrimeFaces 4.0
Jul 25, 2014 8:26:43 PM org.apache.catalina.core.StandardContext startInternal
SCHWERWIEGEND: Error listenerStart
Jul 25, 2014 8:26:43 PM org.apache.catalina.core.StandardContext startInternal
SCHWERWIEGEND: Context [/myPrj] startup failed due to previous errors
Jul 25, 2014 8:26:43 PM org.apache.catalina.core.ApplicationContext log
INFORMATION: Closing Spring root WebApplicationContext
Jul 25, 2014 8:26:43 PM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SCHWERWIEGEND: The web application [/myPrj] registered the JDBC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Jul 25, 2014 8:26:43 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SCHWERWIEGEND: The web application [/myPrj] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak.
Jul 25, 2014 8:26:43 PM org.apache.coyote.AbstractProtocol start
INFORMATION: Starting ProtocolHandler ["http-bio-8080"]
Jul 25, 2014 8:26:43 PM org.apache.coyote.AbstractProtocol start
INFORMATION: Starting ProtocolHandler ["ajp-bio-8009"]
Jul 25, 2014 8:26:43 PM org.apache.catalina.startup.Catalina start
INFORMATION: Server startup in 11322 ms

Unabhängig vom konkreten Problem erst einmal grundsätzliche Punkte:

  1. Warum verwendest du nicht @Temporal(TemporalType.TIMESTAMP) statt der Hibernate-Annotation @Type?

  2. Verwende bitte die passenden BBCodes, um Syntaxhighlighting und die Formatierung der Quellcodes zu erreichen anstelle der [noparse]

[/quote][/noparse]-Tags. Richtig für Java-Code ist [noparse]``````[/noparse], für SQL [noparse][sql][/sql][/noparse] und für Logs etc. [noparse]

[/noparse]. In den [noparse][quote]

[/noparse]-Tags ist das ziemlich unleserlich.

Nun zum Problem:
Du musst die @JoinColumn-Annotation anstelle der @Column-Annotation verwenden, wenn du andere Entitäten referenzierst.

Danke erstmal im Vorfeld. Werds nachher mal ausprobieren. Aber für persönliches Verständnis:

[QUOTE=cmrudolph]Unabhängig vom konkreten Problem erst einmal grundsätzliche Punkte:

  1. Warum verwendest du nicht @Temporal(TemporalType.TIMESTAMP) statt der Hibernate-Annotation @Type?
    [/QUOTE]
    Wo genau meinst du? Meinst du bei “created_at”?

[QUOTE=cmrudolph;98433]
Nun zum Problem:
Du musst die @JoinColumn-Annotation anstelle der @Column-Annotation verwenden, wenn du andere Entitäten referenzierst.[/QUOTE]
@JoinColumn gibt doch nur an das die Tabelle verknüpft ist und @Column gibt die Definition (Aussehen) der Spalte an, oder? Deshalb verstehe ich deine Aussage nicht wieso ich @Column weglassen soll.

P.S.
Bei @OneToOne kann man ja auch den Cascade Type einstellen, den ich bis jetzt noch nicht zu 100% verstanden habe. Ich verstehe es doch richtig, das ich hier denn nicht angeben brauch, da wenn ein User gelöscht oder geändert wird, es ja den “CreatedBy”-User nicht betrifft.

Ja, genau da. Wenn du es mit JPA ausdrücken kannst, dann brauchst du keine Abhängigkeiten zur JPA-Implementierung einführen.

Nein. @JoinColumn definiert das Aussehen der Spalte für die Assoziation. Die beiden Annotationen ähneln sich in einigen Bereichen also.

Der CascadeType hat was damit zu tun, wie “explizit” du referenzierte Entitäten anlegen oder löschen musst. Wenn du z. B. CascadeType.PERSIST definierst, dann brauchst du die referenzierte Entität nicht vorher mit dem EntityManager zu speichern, sondern sie wird mit persistiert, sobald du die referenzierende Entität speicherst.

Was mir in deiner Stacktrace noch aufgefallen ist: warum injizierst du ein UserDAO in den UserService? Das hört sich für mich etwas komisch an, weil DAOs eigentlich keine Beans sind.

*** Edit ***

Ja, das siehst du richtig.

Deine Assoziation ist übrigens aller Wahrscheinlichkeit nach keine @OneToOne-Assoziation, sondern eine @ManyToOne (sonst könnte jeder Benutzer nur genau einen anderen Benutzer anlegen).

Also wenn ich jetzt alles richtig verstanden habe, müsste die Entity wie folgt aussehen

import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
	 
@Entity
@Table(name="user")
public class User { 
	    @Id
	    @GeneratedValue(strategy = GenerationType.IDENTITY)
		@Column(name = "id", unique = true, nullable = false)	    
	    private int id;
	    @Column(name="created_by")
	    @ManyToOne(fetch = FetchType.LAZY)
	    @JoinColumn(name="id")
	    private User created_by;	  
	    @OneToMany(fetch = FetchType.LAZY)
	    @JoinColumn(name="created_by")
	    private List<User> created;
	    @Column(name="created_at", nullable = false)
	    @Temporal(TemporalType.TIMESTAMP)
	    private Date    created_at;
	    @Column(name="blocked", nullable = false)
	    private boolean blocked;
	    @Column(name="deleted", nullable = false)
	    private boolean deleted;
	    @Column(name="activcode", unique = true, nullable = false)
	    private String  activcode;
	    @Column(name="firstname")
	    private String  firstname;
	    @Column(name="lastname")
	    private String  lastname;
	    @Column(name="email", unique = true, nullable = false)
	    private String  email;
	    @Column(name="password", nullable = false)
	    private String  password;
		   
	    public int getId() {
	        return id;
	    }
	 
	    public void setId(int id) {
	        this.id = id;
	    }

	    public User getCreatedBy() {
			return created_by;
	    }
	    
	    public void setCreatedBy(User user) {
			this.created_by = user;
	    }
		
	    public Date getCreatedAt() {
			return created_at;
	    }
		
	    public void setCreatedAt(Date created_at) {
			this.created_at = created_at;
	   }

	   public boolean isBlocked() {
			return blocked;
		}

	   public void setBlocked(boolean blocked) {
			this.blocked = blocked;
		}
				
	   public boolean isDeleted() {
			return deleted;
		}
		
	   public void setDeleted(boolean deleted) {
			this.deleted = deleted;
		}
		
	   public String getActivcode() {
			return activcode;
		}
		
	   public void setActivcode(String activcode) {
			this.activcode = activcode;
		}

	   public String getFirstname() {
	        return firstname;
	    }
	 
	   public void setFirstname(String firstname) {
	        this.firstname = firstname;
	    }

	   public String getLastname() {
			return lastname;
		}
	    
	   public void setLastname(String lastname) {
			this.lastname = lastname;
		}
		
	   public String getEmail() {
			return email;
		}
		
	   public void setEmail(String email) {
			this.email = email;
		}

	   public String getPassword() {
			return password;
		}

	   public void setPassword(String password) {
			this.password = password;
		}
 
           public List<User> getCreated() {
	        return created;
	    }

	   public void setCreated(List<User> created) {
	        this.created = created;
	    }
	    
	    @Override
		public String toString() {
			return "User [id=" + id + ", created_by=" + created_by
					+ ", created=" + created + ", created_at=" + created_at
					+ ", blocked=" + blocked + ", deleted=" + deleted
					+ ", activcode=" + activcode + ", firstname=" + firstname
					+ ", lastname=" + lastname + ", email=" + email
					+ ", password=" + password + "]";
		}
}

Wäre nett wenn Ihr mir ein Feedback geben könntet

So in etwa sollte das aussehen:

import java.util.Date;
import java.util.List;

@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "created_by")
    private User createdBy;
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "createdBy")
    @JoinColumn(name = "created_by")
    private List<User> created;
    @Column(name = "created_at", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdAt;
    @Column(name = "blocked", nullable = false)
    private boolean blocked;
    @Column(name = "deleted", nullable = false)
    private boolean deleted;
    @Column(name = "activcode", unique = true, nullable = false)
    private String activcode;
    @Column(name = "firstname")
    private String firstname;
    @Column(name = "lastname")
    private String lastname;
    @Column(name = "email", unique = true, nullable = false)
    private String email;
    @Column(name = "password", nullable = false)
    private String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public User getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(User user) {
        this.createdBy = user;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date created_at) {
        this.createdAt = created_at;
    }

    public boolean isBlocked() {
        return blocked;
    }

    public void setBlocked(boolean blocked) {
        this.blocked = blocked;
    }

    public boolean isDeleted() {
        return deleted;
    }

    public void setDeleted(boolean deleted) {
        this.deleted = deleted;
    }

    public String getActivcode() {
        return activcode;
    }

    public void setActivcode(String activcode) {
        this.activcode = activcode;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<User> getCreated() {
        return created;
    }

    public void setCreated(List<User> created) {
        this.created = created;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", created_by=" + createdBy
                + ", created=" + created + ", created_at=" + createdAt
                + ", blocked=" + blocked + ", deleted=" + deleted
                + ", activcode=" + activcode + ", firstname=" + firstname
                + ", lastname=" + lastname + ", email=" + email
                + ", password=" + password + "]";
    }
}```

Die @Column-Annotation kommt komplett weg. Außerdem muss bei der @OneToMany-Annotation `mappedBy` gesetzt werden, weil die Beziehung bidirektional ist.
Der Name in der @JoinColumn ist der Name, wie die Join-Spalte benannt werden soll, nicht wie die Zielspalte heißt. Daher muss der Wert "created_by" sein.

Noch allgemeine Hinweise:
- du brauchst nicht überall explizit Namen für die Spalten angeben. Standardmäßig werden die Namen generiert.
- die Felder created_by und created_at würde man eher gemäß Konvention createdBy und createdAt nennen. Die Spaltennamen werden allerdings created_by und created_at heißen, weil in Spaltennamen einer Datenbank andere Konventionen gelten.
- die Setter für createdBy und createdAt würde ich weglassen, weil die Werte unveränderlich sind. Stattdessen würde ich einen öffentlichen Konstruktor erstellen, der das Erstellungsdatum selbst einfügt (aktueller Zeitpunkt) oder übernimmt und den erstellenden Nutzer als Argument übernimmt. Zusätzlich dann einen parameterlosen protected Konstruktor für das Mapping.

P. S.: kann sein, dass bei den Annotationen noch der ein oder andere kleine Fehler drin ist, ich habe das relativ flüchtig korrigiert.

*** Edit ***

Was ich noch vergessen habe zu erwähnen: in der Column-Annotation für die Id-Spalte brauchst du das nullable = false und unique = true nicht. Das gilt immer für Primärschlüssel und kann deshalb weggelassen werden.

Danke für die Entiy cmrudolph. Ich habe darin aber immer noch einen Fehler:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘UserService’ defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean ‘UserDAO’ while setting bean property ‘userDAO’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘UserDAO’ defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Cannot resolve reference to bean ‘SessionFactory’ while setting bean property ‘sessionFactory’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘SessionFactory’ defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn

Ich habe schon mal nachgelesen und gesehen das man die @JoinColum weglässt (http://fruzenshtein.com/bidirectional-many-to-one-association/). Compeliere ich allerdings

    import javax.persistence.*;
    import java.util.Date;
    import java.util.List;
     
    @Entity
    @Table(name = "user")
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "id")
        private int id;
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "created_by")
        private User createdBy;
        @OneToMany(fetch = FetchType.LAZY, mappedBy = "createdBy")
        private List<User> created;
        @Column(name = "created_at", nullable = false)
        @Temporal(TemporalType.TIMESTAMP)
        private Date createdAt;
        @Column(name = "blocked", nullable = false)
        private boolean blocked;
        @Column(name = "deleted", nullable = false)
        private boolean deleted;
        @Column(name = "activcode", unique = true, nullable = false)
        private String activcode;
        @Column(name = "firstname")
        private String firstname;
        @Column(name = "lastname")
        private String lastname;
        @Column(name = "email", unique = true, nullable = false)
        private String email;
        @Column(name = "password", nullable = false)
        private String password;
     
        public int getId() {
            return id;
        }
     
        public void setId(int id) {
            this.id = id;
        }
     
        public User getCreatedBy() {
            return createdBy;
        }
     
        public void setCreatedBy(User user) {
            this.createdBy = user;
        }
     
        public Date getCreatedAt() {
            return createdAt;
        }
     
        public void setCreatedAt(Date created_at) {
            this.createdAt = created_at;
        }
     
        public boolean isBlocked() {
            return blocked;
        }
     
        public void setBlocked(boolean blocked) {
            this.blocked = blocked;
        }
     
        public boolean isDeleted() {
            return deleted;
        }
     
        public void setDeleted(boolean deleted) {
            this.deleted = deleted;
        }
     
        public String getActivcode() {
            return activcode;
        }
     
        public void setActivcode(String activcode) {
            this.activcode = activcode;
        }
     
        public String getFirstname() {
            return firstname;
        }
     
        public void setFirstname(String firstname) {
            this.firstname = firstname;
        }
     
        public String getLastname() {
            return lastname;
        }
     
        public void setLastname(String lastname) {
            this.lastname = lastname;
        }
     
        public String getEmail() {
            return email;
        }
     
        public void setEmail(String email) {
            this.email = email;
        }
     
        public String getPassword() {
            return password;
        }
     
        public void setPassword(String password) {
            this.password = password;
        }
     
        public List<User> getCreated() {
            return created;
        }
     
        public void setCreated(List<User> created) {
            this.created = created;
        }
     
        @Override
        public String toString() {
            return "User [id=" + id + ", created_by=" + createdBy
                    + ", created=" + created + ", created_at=" + createdAt
                    + ", blocked=" + blocked + ", deleted=" + deleted
                    + ", activcode=" + activcode + ", firstname=" + firstname
                    + ", lastname=" + lastname + ", email=" + email
                    + ", password=" + password + "]";
        }
    }

sprich das 2te JoinColumn dann erhalte ich die Fehlermeldung

mappedBy reference an unknown target entity property

Ich verstehe den Compile-Fehler einfach nicht

*** Edit ***

bzw. die überarbeitete Version

import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

@Entity
@Table(name="user")
public class User { 
	    @Id
	    @GeneratedValue(strategy = GenerationType.IDENTITY)    
	    private int id;
	    @ManyToOne(fetch = FetchType.LAZY)
	    @JoinColumn(name = "created_by") 
	    private User    created_by;	    
	    @OneToMany(fetch = FetchType.LAZY, mappedBy = "createdBy")
	    @JoinColumn(name = "created_by")
	    private List<User> created;
	    @Column(name="created_at", nullable = false)
	    @Temporal(TemporalType.TIMESTAMP)
	    private Date    created_at;
	    private boolean blocked;
	    private boolean deleted;
	    @Column(name="activcode", unique = true, nullable = false)
	    private String  activcode;
	    private String  firstname;
	    private String  lastname;
	    @Column(name="email", unique = true, nullable = false)
	    private String  email;
	    @Column(name="password", nullable = false)
	    private String  password;
		    
		public User() {
			   super();
			   
			   this.created_by = null;
			   this.created_at = new Date();

		}

		public User(User created_by, boolean blocked,
				boolean deleted, String activcode, String firstname,
				String lastname, String email, String password) {
			super();
			this.created_by = created_by;
			this.created_at = new Date();
			this.blocked = blocked;
			this.deleted = deleted;
			this.activcode = activcode;
			this.firstname = firstname;
			this.lastname = lastname;
			this.email = email;
			this.password = password;
		}

	    public int getId() {
	        return id;
	    }
	 
	    public void setId(int id) {
	        this.id = id;
	    }

	    public User getCreatedBy() {
			return created_by;
		}

	    public List<User> getCreated() {
			return created;
		}
	    
		public void setCreated(List<User> created) {
			this.created = created;
		}

		public Date getCreatedAt() {
			return created_at;
		}

		public boolean isBlocked() {
			return blocked;
		}

		public void setBlocked(boolean blocked) {
			this.blocked = blocked;
		}
		
		public boolean isDeleted() {
			return deleted;
		}
		
		public void setDeleted(boolean deleted) {
			this.deleted = deleted;
		}
		
		public String getActivcode() {
			return activcode;
		}
		
		public void setActivcode(String activcode) {
			this.activcode = activcode;
		}

	    public String getFirstname() {
	        return firstname;
	    }
	 
	    public void setFirstname(String firstname) {
	        this.firstname = firstname;
	    }

	    public String getLastname() {
			return lastname;
		}
	    
		public void setLastname(String lastname) {
			this.lastname = lastname;
		}
		
		public String getEmail() {
			return email;
		}
		
		public void setEmail(String email) {
			this.email = email;
		}
		
		public String getPassword() {
			return password;
		}
		
		public void setPassword(String password) {
			this.password = password;
		}

	 
	    @Override
		public String toString() {
			return "User [id=" + id + ", created_by=" + created_by
					+ ", created_at=" + created_at + ", blocked=" + blocked
					+ ", deleted=" + deleted + ", activcode=" + activcode
					+ ", firstname=" + firstname + ", lastname=" + lastname
					+ ", email=" + email + ", password=" + password + "]";
		}
}

Das stimmt für die Referenz, an der mappedBy steht, weil in der Datenbank dafür keine Spalte angelegt wird.
Du kannst eigentlich alle name = “…” in den Annotationen weglassen, weil sinnvolle Defaultwerte generiert werden. Interessant wird die manuelle Namensvergabe dann, wenn du bereits ein bestehendes Datenbankschema hast, an das du dich halten musst, oder ein Name generiert wird, der ein reserviertes Schlüsselwort in SQL ist.
Wenn du die name = “…” weglässt und eine “leere” Annotation übrig bleibt, dann kannst du sie auch ganz weglassen (gilt theoretisch auch für die @Table-Annotation).

Ich habe die Entity mal mit hibernate 4.3.6 getestet und sie funktioniert so (habe eigentlich nur die “überflüssigen” Annotationen entfernt):

import java.util.Date;
import java.util.List;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @ManyToOne(fetch = FetchType.LAZY)
    private User createdBy;
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "createdBy")
    private List<User> created;
    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdAt;
    @Column(nullable = false)
    private boolean blocked;
    @Column(nullable = false)
    private boolean deleted;
    @Column(unique = true, nullable = false)
    private String activcode;
    private String firstname;
    private String lastname;
    @Column(unique = true, nullable = false)
    private String email;
    @Column(nullable = false)
    private String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public User getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(User user) {
        this.createdBy = user;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date created_at) {
        this.createdAt = created_at;
    }

    public boolean isBlocked() {
        return blocked;
    }

    public void setBlocked(boolean blocked) {
        this.blocked = blocked;
    }

    public boolean isDeleted() {
        return deleted;
    }

    public void setDeleted(boolean deleted) {
        this.deleted = deleted;
    }

    public String getActivcode() {
        return activcode;
    }

    public void setActivcode(String activcode) {
        this.activcode = activcode;
    }

    public String getFirstname() {
        return firstname;
    }

    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public void setLastname(String lastname) {
        this.lastname = lastname;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<User> getCreated() {
        return created;
    }

    public void setCreated(List<User> created) {
        this.created = created;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", created_by=" + createdBy
                + ", created=" + created + ", created_at=" + createdAt
                + ", blocked=" + blocked + ", deleted=" + deleted
                + ", activcode=" + activcode + ", firstname=" + firstname
                + ", lastname=" + lastname + ", email=" + email
                + ", password=" + password + "]";
    }
}```

Mit MySQL 5.6.14 wird die Entity ordentlich generiert:

Hibernate: create table User (id integer not null auto_increment, activcode varchar(255) not null, blocked bit not null, createdAt datetime not null, deleted bit not null, email varchar(255) not null, firstname varchar(255), lastname varchar(255), password varchar(255) not null, createdBy_id integer, primary key (id))
Hibernate: alter table User add constraint UK_5l4pu99vbetwpbi945j6snbrs unique (activcode)
Hibernate: alter table User add constraint UK_e6gkqunxajvyxl5uctpl2vl2p unique (email)
Hibernate: alter table User add constraint FK_9w1lvibkjsisdbs0u3v05r138 foreign key (createdBy_id) references User (id)



Ein MS SQL Server stört sich allerdings an dem Tabellennamen "User" (deshalb oben das "theoretisch"):

Hibernate: create table User (id int identity not null, activcode varchar(255) not null, blocked bit not null, createdat datetime2 not null, deleted bit not null, email varchar(255) not null, firstname varchar(255), lastname varchar(255), password varchar(255) not null, createdby_id int, primary key (id))
2014-07-29 06:53:01,116 ERROR org.hibernate.tool.hbm2ddl.SchemaExport - HHH000389: Unsuccessful: create table User (id int identity not null, activcode varchar(255) not null, blocked bit not null, createdat datetime2 not null, deleted bit not null, email varchar(255) not null, firstname varchar(255), lastname varchar(255), password varchar(255) not null, createdby_id int, primary key (id))
2014-07-29 06:53:01,117 ERROR org.hibernate.tool.hbm2ddl.SchemaExport - Incorrect syntax near the keyword ‘User’.
Hibernate: alter table User add constraint UK_5l4pu99vbetwpbi945j6snbrs unique (activcode)
2014-07-29 06:53:01,133 ERROR org.hibernate.tool.hbm2ddl.SchemaExport - HHH000389: Unsuccessful: alter table User add constraint UK_5l4pu99vbetwpbi945j6snbrs unique (activcode)
2014-07-29 06:53:01,134 ERROR org.hibernate.tool.hbm2ddl.SchemaExport - Incorrect syntax near the keyword ‘User’.
Hibernate: alter table User add constraint UK_e6gkqunxajvyxl5uctpl2vl2p unique (email)
2014-07-29 06:53:01,135 ERROR org.hibernate.tool.hbm2ddl.SchemaExport - HHH000389: Unsuccessful: alter table User add constraint UK_e6gkqunxajvyxl5uctpl2vl2p unique (email)
2014-07-29 06:53:01,136 ERROR org.hibernate.tool.hbm2ddl.SchemaExport - Incorrect syntax near the keyword ‘User’.
Hibernate: alter table User add constraint FK_9alvrs7lvsj5lru1hgp703tda foreign key (createdby_id) references User
2014-07-29 06:53:01,158 ERROR org.hibernate.tool.hbm2ddl.SchemaExport - HHH000389: Unsuccessful: alter table User add constraint FK_9alvrs7lvsj5lru1hgp703tda foreign key (createdby_id) references User
2014-07-29 06:53:01,158 ERROR org.hibernate.tool.hbm2ddl.SchemaExport - Incorrect syntax near the keyword ‘User’.

Für MS SQL ist User ein reserviertes Keyword. Das Problem kann umgangen werden, wenn man der Entity einen anderen Tabellennamen zuweist. Ansonsten scheint alles korrekt.

Ach noch eine Sache habe ich vergessen zu erwähnen: wenn du das Schema nicht generieren lässt, sondern manuell erzeugst und auf Windows mit MySQL testest, der MySQL-Server später aber auf Linux läuft, musst du auf die Groß-/Kleinschreibung achten.
Du siehst, dass die Tabellennamen standardmäßig mit einem Großbuchstaben beginnen. Unter Windows ist MySQL die Schreibweise egal. Unter Linux aber nicht (das liegt iirc am Dateisystem, welches unter Linux zwischen Groß-/Kleinschreibung unterscheidet. Die Tabellen werden als einzelne Dateien angelegt und bei falscher Schreibweise ggf. nicht gefunden).

*** Edit ***

Da du mit Hibernate 4.3 arbeitest (aus deiner Fehlermeldung sieht man zwar nur, dass du hibernate 4 verwendest, aber ich gehe davon aus, dass du die aktuellste Version verwendest), kannst du deine Indizes auch mit JPA 2.1 Annotationen direkt angeben:
@Table(indexes = {@Index(columnList = "blocked"), @Index(columnList = "deleted")})

Die createdAt-Spalte wird aber wider Erwarten als DateTime angelegt und nicht als Timestamp.

Was Datums- / Zeitwerte angeht arbeite ich mittlerweile mit JSR 310 und für das Mapping nutze ich dann ThreeTen JPA. Geht natürlich nur mit Java 8.

Und wird damit von keinem aktuellen Enterpriseserver unterstützt. :slight_smile:

Stimmt auffallend :o)
Mit einem Tomcat + Spring + Hibernate - Stack funktioniert das aber hervorragend :wink:
Für „echtes“ JavaEE fühle ich mich (als Hobbyentwickler) noch nicht enterprisemäßig genug :stuck_out_tongue: