Fremdschlüsselfehler beim Speichern mehrerer Objekte mit Hibernate

Dosihris

Grünschnabel
Hi,

Ich habe folgendes Problem, wo mir selbst im Hibernateforum keiner helfen konnte. Aber vielleicht klappt es ja hier.

Ich habe zwei Tabellen. Customer für Kundeninformationen und CustomerContact für Kontaktinformationen für jeden Kunden. Diese Daten sind aus Performancegründen getrennt.

Die Customer-Tabelle verfügt über eine Spalte ID, welche autoinc ist (automatisch hochzählen) und somit auch ein Primärschlüssel. Die Tabelle CustomerContact enthält eine Spalte CustomerID, welche einfach nur ein Integer ist (und auch Primärschlüssel). Die Tabelle Customer hat also einen Fremdschlüssel von der Spalte ID auf die Spalte CustomerID der Tabelle CustomerContacts. (Hoffe ich konnte das soweit ordentlich erklären).

Das Problem ist nun folgendes. Wenn ich ein customer-Objekt in Java habe, also neu anlege, dann befülle ich alle Properties mit den entsprechenden Werten. Z.B. sage ich

Code:
Customer customer=new Customer();
customer.setName("Name");
customer.setFirstName("FirstName");

customer.setCustomercontact(new Customercontact());

customer.getCustomercontact.setMail("mail@server.com");

So, ich setze also weder die ID von customer (weil die ja durch die AutoInc-Spalte automatisch zugewiesen wird, noch die CustomerID).

Beim Speichern des gesamten Objektes kommt folgende Exception.

Code:
org.springframework.dao.DataIntegrityViolationException: could not insert: [de.nfranze.sf.model.Customer]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [de.nfranze.sf.model.Customer]
Caused by: 
org.hibernate.exception.ConstraintViolationException: could not insert: [de.nfranze.sf.model.Customer]
	at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
	at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
	at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:40)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2093)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2573)
	at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:47)
	at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
	at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:290)
	at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:180)
	at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:108)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:186)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:175)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:98)
	at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
	at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
	at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
	at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
	at org.springframework.orm.hibernate3.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:679)
	at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:362)
	at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:676)
	at de.nfranze.sf.logic.dao.CustomerDAO.Save(CustomerDAO.java:38)
	at de.nfranze.sf.logic.manager.CustomerManager.Create(CustomerManager.java:24)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:280)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:187)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:154)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:176)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:210)
	at $Proxy8.Create(Unknown Source)
	at de.nfranze.sf.controller.RegisterWizardController.processFinish(RegisterWizardController.java:160)
	at org.springframework.web.servlet.mvc.AbstractWizardFormController.validatePagesAndFinish(AbstractWizardFormController.java:650)
	at org.springframework.web.servlet.mvc.AbstractWizardFormController.processFormSubmission(AbstractWizardFormController.java:490)
	at org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:250)
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:45)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:820)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:755)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:396)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:360)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
	at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:174)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:77)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:138)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:202)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:869)
	at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:664)
	at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
	at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
	at java.lang.Thread.run(Unknown Source)
Caused by: java.sql.SQLException: Cannot add or update a child row: a foreign key constraint fails (`sf/customer`, CONSTRAINT `FK_contact` FOREIGN KEY (`id`) REFERENCES `custcontact` (`customerid`))
	at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2975)
	at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1600)
	at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1129)
	at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:681)
	at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1368)
	at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1283)
	at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1268)
	at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:73)
	at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:33)

Ich nehme an, dass folgendes passiert. Er will das Customer-Objekt in die Datenbank schreiben, vergibt die ID, z.B. 5, will dann die CustomerContact-Daten speichern, aber das Feld CustomerID ist ja null. Er erwartet aber 5. -> BOOM...

Nun ist die Frage, wie schaffe ich es, dass Hibernate automatisch diese 5, die es für die Spalte ID vergeben hat, automatisch an die Spalten weitergibt, die durch den Fremdschlüssel referenziert sind? Da gibt es bestimmt etwas, wie man die hbm.xml-Dateien konfigurieren kann.
Ich nutze ein Ant-Task, um mit HibernateTools diese Dateien anhand meiner MySQL-Datenbank zu generieren. Also müsste ich eigentlich die build.xml so anpassen, dass die hbm.xml-Dateien so generiert werden, dass das mit den Fremdschlüsseln klappt...

So, nun hab ich ja echt viel geschrieben. Hoffe das Problem ist klar geworden.

Hier mal noch meine build.xml, falls diese jemanden interessiert.
Code:
	<target name="Generate Database Objects" description="Middlegen hbm-Generation from MySQL">
		<taskdef name="middlegen" classname="middlegen.MiddlegenTask">
			<classpath refid="master-classpath"/>
		</taskdef>

		<taskdef name="hibernatetool" classname="org.hibernate.tool.ant.HibernateToolTask">
			<classpath refid="master-classpath"/>
		</taskdef>

		<middlegen
			 appname="Sf"
			 gui="false"
			 databaseurl="jdbc:mysql://fileserver/sf"
			 driver="com.mysql.jdbc.Driver"
			 username="root"
			 password="blabla"
			 schema="sf"
			 includeViews="false"
      	>
			<hibernate 
	    	  	destination="${web.dir}/src"
    	  		package="de.nfranze.sf.model"
	      		standardGeneratorScheme="native"
		      	javaTypeMapper="middlegen.plugins.hibernate.HibernateJavaTypeMapper"/>
		</middlegen>

		<hibernatetool destdir="${web.dir}/src">
			<configuration>
				<fileset dir="${model.dir}">
					<include name="**/*.hbm.xml"/>
				</fileset>
			</configuration>
			<classpath refid="master-classpath"/>
			
			<hbm2java jdk5="true"/>
		</hibernatetool>
	</target>
 
Als Ergänzung habe ich mir gedacht, zeige ich euch mal noch die beiden hbm.xml-Dateien. Vllt. kann man daraus noch ersichtlicher erkennen, warum das Abspeichern nicht funktioniert.

Als erstes meine Customer-Tabelle (Customer.hbm.xml)
Code:
<?xml version="1.0"?> 
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" > 
    
<hibernate-mapping> 
<!-- 
    Created by the Middlegen Hibernate plugin 2.1 

    http://boss.bekk.no/boss/middlegen/ 
    http://www.hibernate.org/ 
--> 

<class 
    name="de.nfranze.sf.model.Customer" 
    table="customer" 
> 

    <id 
        name="id" 
        type="java.lang.Integer" 
        column="id" 
    > 
        <generator class="native" /> 
    </id> 

    <property 
        name="state" 
        type="short" 
        column="state" 
        not-null="true" 
        length="10" 
    /> 
    <property 
        name="nick" 
        type="java.lang.String" 
        column="nick" 
        not-null="true" 
        length="40" 
    /> 
    <property 
        name="name" 
        type="java.lang.String" 
        column="name" 
        not-null="true" 
        length="50" 
    /> 
    <property 
        name="firstname" 
        type="java.lang.String" 
        column="firstname" 
        not-null="true" 
        length="40" 
    /> 
    <property 
        name="birthdate" 
        type="java.sql.Date" 
        column="birthdate" 
        length="10" 
    /> 

    <!-- Associations --> 
  
    <!-- bi-directional one-to-one association to Custcontact --> 
    <one-to-one 
        name="custcontact" 
        class="de.nfranze.sf.model.Custcontact" 
        outer-join="auto" 
        constrained="true" 
    /> 

</class> 
</hibernate-mapping>


Und nun die Custcontact.hbm.xml, welche die Kontaktdaten zu diesem Kontakt enthält.
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
    
<hibernate-mapping>
<!-- 
    Created by the Middlegen Hibernate plugin 2.1

    http://boss.bekk.no/boss/middlegen/
    http://www.hibernate.org/
-->

<class 
    name="de.nfranze.sf.model.Custcontact" 
    table="custcontact"
>

    <id
        name="customerid"
        type="java.lang.Integer"
        column="customerid"
    >
        <generator class="native" />
    </id>

    <property
        name="phone"
        type="java.lang.String"
        column="phone"
        length="40"
    />
    <property
        name="fax"
        type="java.lang.String"
        column="fax"
        length="40"
    />
    <property
        name="mail"
        type="java.lang.String"
        column="mail"
        length="40"
    />
    <property
        name="mobile"
        type="java.lang.String"
        column="mobile"
        not-null="true"
        length="45"
    />

    <!-- Associations -->
  
    <!-- bi-directional one-to-one association to Customer -->
    <one-to-one
        name="customer"
        class="de.nfranze.sf.model.Customer"
        outer-join="auto"
    />

</class>
</hibernate-mapping>

Wobei mir auffällt.. Wo steht denn eigentlich, über welche Spalten die Schlüssel verbunden sind?
 
Hallo,

hier mal ein kleines Mini Beispiel zu Spring und Hibernate:

Unser Customer:
Java:
/**
 * 
 */
package de.tutorials.domain;

import org.apache.commons.lang.builder.ToStringBuilder;

/**
 * @author Tom
 */
public class Customer {
  Long id = -1L;
  String name;
  CustomerContact customerContact;


  public Customer() {
  }


  public Customer(String name) {
    this.name = name;
  }


  /**
   * @return the id
   */
  public Long getId() {
    return id;
  }


  /**
   * @param id the id to set
   */
  public void setId(Long id) {
    this.id = id;
  }


  /**
   * @return the name
   */
  public String getName() {
    return name;
  }


  /**
   * @param name the name to set
   */
  public void setName(String name) {
    this.name = name;
  }


  /**
   * @return the customerContact
   */
  public CustomerContact getCustomerContact() {
    return customerContact;
  }


  /**
   * @param customerContact the customerContact to set
   */
  public void setCustomerContact(CustomerContact customerContact) {
    this.customerContact = customerContact;
  }


  /*
   * (non-Javadoc)
   * @see java.lang.Object#hashCode()
   */
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((customerContact == null) ? 0 : customerContact.hashCode());
    result = prime * result + ((name == null) ? 0 : name.hashCode());
    return result;
  }


  /*
   * (non-Javadoc)
   * @see java.lang.Object#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    final Customer other = (Customer) obj;
    if (customerContact == null) {
      if (other.customerContact != null) return false;
    } else if (!customerContact.equals(other.customerContact)) return false;
    if (name == null) {
      if (other.name != null) return false;
    } else if (!name.equals(other.name)) return false;
    return true;
  }


  @Override
  public String toString() {
    return ToStringBuilder.reflectionToString(this);
  }
}

Das Hibernate Mapping für Customer:
XML:
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
	<class name="de.tutorials.domain.Customer" table="customer">

		<id name="id" column="id" type="java.lang.Long"
			unsaved-value="-1">
			<generator class="native" />
		</id>

		<property name="name" type="java.lang.String" update="true"
			insert="true" column="name" unique="true" />

		<many-to-one name="customerContact"
			class="de.tutorials.domain.CustomerContact" cascade="all"
			unique="true" column="customercontactid" fetch="join" lazy="false"/>
	</class>
</hibernate-mapping>

Unser CustomerContact:
Java:
/**
 * 
 */
package de.tutorials.domain;

import org.apache.commons.lang.builder.ToStringBuilder;

/**
 * @author Tom
 *
 */
public class CustomerContact {
  Long id = -1L;;
  String mail;
 
  
  public CustomerContact(){
    
  }
  
  /**
   * @param mail
   */
  public CustomerContact(String mail) {
    super();
    this.mail = mail;
  }

  /**
   * @return the id
   */
  public Long getId() {
    return id;
  }
  /**
   * @param id the id to set
   */
  private void setId(Long id) {
    this.id = id;
  }
  /**
   * @return the mail
   */
  public String getMail() {
    return mail;
  }
  /**
   * @param mail the mail to set
   */
  public void setMail(String mail) {
    this.mail = mail;
  }
  

  /* (non-Javadoc)
   * @see java.lang.Object#hashCode()
   */
  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((mail == null) ? 0 : mail.hashCode());
    return result;
  }

  /* (non-Javadoc)
   * @see java.lang.Object#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    final CustomerContact other = (CustomerContact) obj;
    if (mail == null) {
      if (other.mail != null) return false;
    } else if (!mail.equals(other.mail)) return false;
    return true;
  }
  
  @Override
  public String toString() {
    return ToStringBuilder.reflectionToString(this);
  }
}

Das Hibernate Mapping für Customer Contact
XML:
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
	<class name="de.tutorials.domain.CustomerContact"
		table="customercontact">

		<id name="id" column="id" type="java.lang.Long"
			unsaved-value="-1">
			<generator class="native" />
		</id>

		<property name="mail" type="java.lang.String" update="true"
			insert="true" column="mail" unique="true" />
	</class>

</hibernate-mapping>

Unser ICustomerAdministrationService:
Java:
/**
 * 
 */
package de.tutorials.service;

import java.util.List;

import de.tutorials.domain.Customer;

/**
 * @author Tom
 *
 */
public interface ICustomerAdministrationService {
  void save(Customer customer);
  void delete(Customer customer);
  Customer getCustomerById(Long id);
  Customer getCustomerByName(String name);
  List<Customer> findAll();
}

Unsere Implementierung:
Java:
/**
 * 
 */
package de.tutorials.service.internal;

import java.util.List;

import de.tutorials.dao.ICustomerDAO;
import de.tutorials.domain.Customer;
import de.tutorials.service.ICustomerAdministrationService;

/**
 * @author Tom
 */
public class CustomerAdministrationService implements ICustomerAdministrationService {

  ICustomerDAO customerDAO;


  public void delete(Customer customer) {
    getCustomerDAO().makeTransient(customer);
  }


  public List<Customer> findAll() {
    return getCustomerDAO().findAll();
  }


  public Customer getCustomerById(Long id) {
    return getCustomerDAO().getCustomerById(id);
  }


  public Customer getCustomerByName(String name) {
    return getCustomerDAO().getCustomerByName(name);
  }


  public void save(Customer customer) {
    getCustomerDAO().makePersistent(customer);
  }


  /**
   * @return the customerDAO
   */
  public ICustomerDAO getCustomerDAO() {
    return customerDAO;
  }


  /**
   * @param customerDAO the customerDAO to set
   */
  public void setCustomerDAO(ICustomerDAO customerDAO) {
    this.customerDAO = customerDAO;
  }

}

Unser ICustomerDAO:
Java:
/**
 * 
 */
package de.tutorials.dao;

import java.util.List;

import de.tutorials.domain.Customer;

/**
 * @author Tom
 *
 */
public interface ICustomerDAO {
  void makePersistent(Customer customer);
  void makeTransient(Customer customer);
  Customer getCustomerById(Long id);
  Customer getCustomerByName(String name);
  List<Customer> findAll();
}

Unsere CustomerDAO Implementierung:
Java:
/**
 * 
 */
package de.tutorials.dao.internal;

import java.util.List;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import de.tutorials.dao.ICustomerDAO;
import de.tutorials.domain.Customer;

/**
 * @author Tom
 *
 */
public class CustomerDAO extends HibernateDaoSupport implements ICustomerDAO{

  @SuppressWarnings("unchecked")
  public List<Customer> findAll() {
    return getHibernateTemplate().find("from Customer");
  }

  public Customer getCustomerById(Long id) {
    return Customer.class.cast(getHibernateTemplate().get(Customer.class, id));
  }

  public Customer getCustomerByName(String name) {
    return Customer.class.cast(getHibernateTemplate().find("from Customer customer where customer.name = ?",name));
  }

  public void makePersistent(Customer customer) {
    getHibernateTemplate().merge(customer);
  }

  public void makeTransient(Customer customer) {
    getHibernateTemplate().delete(customer);
  }
}

Hier die Spring Konfiguration:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"
	default-lazy-init="true">
	
	
	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="location" value="conf/jdbc.properties"/>
	</bean>
	
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory">
			<ref bean="sessionFactory"/>
		</property>
	</bean>
	
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="mappingDirectoryLocations">
		<list>
			<value>classpath:/de/tutorials/domain</value>
		</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.generate_statistics">true</prop>
			</props>
		</property>
	</bean>
	
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${jdbc.driverClassName}"/>
		<property name="url" value="${jdbc.url}"/>
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
	</bean>
	
	<bean name="CustomerAdministrationService"
		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
		<property name="target">
			<bean class="de.tutorials.service.internal.CustomerAdministrationService">
				<property name="customerDAO">
					<ref bean="CustomerDAO"/>
				</property>
			</bean>
		</property>
		<property name="proxyInterfaces">
			<list>
				<value>de.tutorials.service.ICustomerAdministrationService</value>
			</list>
		</property>
		<property name="transactionAttributes">
			<props>
				<prop key="save*">PROPAGATION_REQUIRED</prop>
				<prop key="delete*">PROPAGATION_REQUIRED</prop>
			</props>
		</property>
	</bean>
	
	<bean name="CustomerDAO" class="de.tutorials.dao.internal.CustomerDAO">
		<property name="sessionFactory">
			<ref bean="sessionFactory"/>
		</property>
	</bean>
</beans>

Unser jdbc.properties:
Code:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/example
jdbc.username=root
jdbc.password=tutorials
hibernate.dialect=org.hibernate.dialect.MySQLDialect

Die Datenbanktabellen:
SQL:
drop table customer;
drop table customercontact;
create table customer(id int not null auto_increment, name varchar(32), customercontactid int, primary key(id));
create table customercontact(id int not null auto_increment, mail varchar(32), primary key(id));
alter table customer add foreign key fk_customer(customercontactid) references customercontact(id) on delete cascade;

Das Beispiel:
Java:
/**
 * 
 */
package de.tutorials;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;

import de.tutorials.domain.Customer;
import de.tutorials.domain.CustomerContact;
import de.tutorials.service.ICustomerAdministrationService;

/**
 * @author Tom
 */
public class Main {

  /**
   * @param args
   */
  public static void main(String[] args) {
    ApplicationContext applicationContext = new FileSystemXmlApplicationContext("conf/applicationContext.xml");
    ICustomerAdministrationService customerAdministrationService = (ICustomerAdministrationService) applicationContext
      .getBean("CustomerAdministrationService");
    
    Customer tom = new Customer("Thomas Darimont");
    tom.setCustomerContact(new CustomerContact("tom@tutorials.de"));
    customerAdministrationService.save(tom);
    
    Customer fritz = new Customer("Fritz Bubu");
    fritz.setCustomerContact(new CustomerContact("bubu@fritz.de"));
    customerAdministrationService.save(fritz);
    
    for(Customer customer : customerAdministrationService.findAll()){
      System.out.println(customer);
    }
  }
}

Ausgabe:
Code:
20.03.2007 00:40:21 org.springframework.core.CollectionFactory <clinit>
INFO: JDK 1.4+ collections available
20.03.2007 00:40:21 org.springframework.core.CollectionFactory <clinit>
INFO: Commons Collections 3.x available
20.03.2007 00:40:21 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from file [C:\Dokumente und Einstellungen\Tom\workspace\de.tutorials.training.mini-spring-hibernate\conf\applicationContext.xml]
20.03.2007 00:40:21 org.springframework.context.support.AbstractRefreshableApplicationContext refreshBeanFactory
INFO: Bean factory for application context [org.springframework.context.support.FileSystemXmlApplicationContext;hashCode=5439109]: org.springframework.beans.factory.support.DefaultListableBeanFactory defining beans [propertyConfigurer,transactionManager,sessionFactory,dataSource,CustomerAdministrationService,CustomerDAO]; root of BeanFactory hierarchy
20.03.2007 00:40:21 org.springframework.context.support.AbstractApplicationContext refresh
INFO: 6 beans defined in application context [org.springframework.context.support.FileSystemXmlApplicationContext;hashCode=5439109]
20.03.2007 00:40:21 org.springframework.core.io.support.PropertiesLoaderSupport loadProperties
INFO: Loading properties file from file [C:\Dokumente und Einstellungen\Tom\workspace\de.tutorials.training.mini-spring-hibernate\conf\jdbc.properties]
20.03.2007 00:40:21 org.springframework.context.support.AbstractApplicationContext initMessageSource
INFO: Unable to locate MessageSource with name 'messageSource': using default [org.springframework.context.support.DelegatingMessageSource@15b0afd]
20.03.2007 00:40:21 org.springframework.context.support.AbstractApplicationContext initApplicationEventMulticaster
INFO: Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [org.springframework.context.event.SimpleApplicationEventMulticaster@37fb1e]
20.03.2007 00:40:21 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in factory [org.springframework.beans.factory.support.DefaultListableBeanFactory defining beans [propertyConfigurer,transactionManager,sessionFactory,dataSource,CustomerAdministrationService,CustomerDAO]; root of BeanFactory hierarchy]
20.03.2007 00:40:21 org.springframework.aop.framework.DefaultAopProxyFactory <clinit>
INFO: CGLIB2 available: proxyTargetClass feature enabled
20.03.2007 00:40:21 org.springframework.jdbc.datasource.DriverManagerDataSource setDriverClassName
INFO: Loaded JDBC driver: com.mysql.jdbc.Driver
20.03.2007 00:40:22 org.hibernate.cfg.Environment <clinit>
INFO: Hibernate 3.2.1
20.03.2007 00:40:22 org.hibernate.cfg.Environment <clinit>
INFO: hibernate.properties not found
20.03.2007 00:40:22 org.hibernate.cfg.Environment buildBytecodeProvider
INFO: Bytecode provider name : cglib
20.03.2007 00:40:22 org.hibernate.cfg.Environment <clinit>
INFO: using JDK 1.4 java.sql.Timestamp handling
20.03.2007 00:40:22 org.hibernate.cfg.Configuration addFile
INFO: Reading mappings from file: C:\Dokumente und Einstellungen\Tom\workspace\de.tutorials.training.mini-spring-hibernate\bin\de\tutorials\domain\Customer.hbm.xml
20.03.2007 00:40:22 org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: de.tutorials.domain.Customer -> customer
20.03.2007 00:40:22 org.hibernate.cfg.Configuration addFile
INFO: Reading mappings from file: C:\Dokumente und Einstellungen\Tom\workspace\de.tutorials.training.mini-spring-hibernate\bin\de\tutorials\domain\CustomerContact.hbm.xml
20.03.2007 00:40:22 org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: de.tutorials.domain.CustomerContact -> customercontact
20.03.2007 00:40:22 org.springframework.orm.hibernate3.LocalSessionFactoryBean buildSessionFactory
INFO: Building new Hibernate SessionFactory
20.03.2007 00:40:22 org.hibernate.connection.ConnectionProviderFactory newConnectionProvider
INFO: Initializing connection provider: org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: RDBMS: MySQL, version: 5.0.22-community-nt
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC driver: MySQL-AB JDBC Driver, version: mysql-connector-java-5.0.4 ( $Date: 2006-10-19 17:47:48 +0200 (Thu, 19 Oct 2006) $, $Revision: 5908 $ )
20.03.2007 00:40:22 org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.MySQLDialect
20.03.2007 00:40:22 org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
20.03.2007 00:40:22 org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): enabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Connection release mode: on_close
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Maximum outer join fetch depth: 2
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
20.03.2007 00:40:22 org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: JPA-QL strict compliance: disabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.NoCacheProvider
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: disabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: enabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
20.03.2007 00:40:22 org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: pojo
20.03.2007 00:40:22 org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
20.03.2007 00:40:23 org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
20.03.2007 00:40:23 org.springframework.orm.hibernate3.HibernateTransactionManager afterPropertiesSet
INFO: Using DataSource [org.springframework.jdbc.datasource.DriverManagerDataSource@1d95da8] of Hibernate SessionFactory for HibernateTransactionManager
Hibernate: insert into customercontact (mail) values (?)
Hibernate: insert into customer (name, customercontactid) values (?, ?)
Hibernate: insert into customercontact (mail) values (?)
Hibernate: insert into customer (name, customercontactid) values (?, ?)
Hibernate: select customer0_.id as id0_, customer0_.name as name0_, customer0_.customercontactid as customer3_0_ from customer customer0_
Hibernate: select customerco0_.id as id1_0_, customerco0_.mail as mail1_0_ from customercontact customerco0_ where customerco0_.id=?
Hibernate: select customerco0_.id as id1_0_, customerco0_.mail as mail1_0_ from customercontact customerco0_ where customerco0_.id=?
de.tutorials.domain.Customer@f102d3[id=1,name=Thomas Darimont,customerContact=de.tutorials.domain.CustomerContact@1d6747b[id=1,mail=tom@tutorials.de]]
de.tutorials.domain.Customer@f07355[id=2,name=Fritz Bubu,customerContact=de.tutorials.domain.CustomerContact@8aeb74[id=2,mail=bubu@fritz.de]]

... in der Datenbank:
SQL:
mysql> select * from customer;
+----+-----------------+-------------------+
| id | name            | customercontactid |
+----+-----------------+-------------------+
|  1 | Thomas Darimont |                 1 |
|  2 | Fritz Bubu      |                 2 |
+----+-----------------+-------------------+
2 rows in set (0.00 sec)

mysql> select * from customercontact;
+----+------------------+
| id | mail             |
+----+------------------+
|  1 | tom @ tutorials.de |
|  2 | bubu @ fritz.de    |
+----+------------------+
2 rows in set (0.00 sec)

Gruß Tom
 

Anhänge

  • de.tutorials.training.mini-spring-hibernate.zip
    15,7 KB · Aufrufe: 21
Zuletzt bearbeitet von einem Moderator:
Leider funktioniert es so bei mir nicht. Ich habe beim durcharbeiten folgende Unterschiede festgestellt...

1. Mein Customer hat immer nur einen Kontakt, also eine one-to-one-Beziehung. Eigentlich sollte das ja keinen so großen unterschied machen.

2. Ich habe bemerkt, dass du nicht Save oder SaveOrUpdate nutzt, sondern Merge. Warum dass denn? Ich habe bisher immer SaveOrUpdate genutzt. Da kommt bei mir ja auch meine Exception. Bei Merge kommt ne andere Exception.

3. Hast du ja bei jeder Property in den hbm.xml-Dateien jeweils die Attribute update="true" und insert="true" gesetzt.
Ich generiere ja meine Dateien mit Middlegen.

Der setzt diese Attribute nicht. Und ich hab recht viele Spalten.Weiterhin hattest du überall Version 3.0 (DTD 3.0//EN) zu stehen. Hast du das selbst getippt?
Der generiert leider standardmäßig die 2.0-Version. Ist es eigentlich notwendig, dass in Customercontact die Spalte mit dem Primärschlüssel auch Autoinc ist?
 
Hallo,

1. Mein Customer hat immer nur einen Kontakt, also eine one-to-one-Beziehung. Eigentlich sollte das ja keinen so großen unterschied machen.
Eine many-to-one mit unique = true == one-to-one mit Fremdschlüssel...
http://www.hibernate.org/hib_docs/v3/reference/en/html_single/#mapping-declaration-onetoone
" Alternatively, a foreign key with a unique constraint, from Employee to Person, may be expressed as:"...

2. Ich habe bemerkt, dass du nicht Save oder SaveOrUpdate nutzt, sondern Merge. Warum dass denn? Ich habe bisher immer SaveOrUpdate genutzt. Da kommt bei mir ja auch meine Exception. Bei Merge kommt ne andere Exception.
merge(...) ist das JPA kompatible pendant zu saveOrupdate(..)

3. Hast du ja bei jeder Property in den hbm.xml-Dateien jeweils die Attribute update="true" und insert="true" gesetzt.
Ich generiere ja meine Dateien mit Middlegen
Afaik sind das defaults die ich nur explizit erwähne...

Der generiert leider standardmäßig die 2.0-Version. Ist es eigentlich notwendig, dass in Customercontact die Spalte mit dem Primärschlüssel auch Autoinc ist?
Nein, das war nur der Einfachheit wegen...

Gruß Tom
 
Ok, das heisst also das wir beide so gut wie das gleiche haben, aber bei mir kommt eine Exception.. :) Das is ja wiedermal typisch. Ich werd auch mal alle meine Dateien posten, vllt. siehst du ja noch weitere Unterschiede, die mir entgangen sind.

Der Customer:
Code:
package de.nfranze.sf.model;
// Generated 20.03.2007 13:44:12 by Hibernate Tools 3.2.0.b9


import java.sql.Date;

/**
 * Customer generated by hbm2java
 */
public class Customer  implements java.io.Serializable {


     private Integer id;
     private int standid;
     private short state;
     private String nick;
     private String password;
     private String gender;
     private String name;
     private String firstname;
     private String birthname;
     private String familystate;
     private Date birthdate;
     private String titel;
     private short active;
     private String activationcode;
     private String pwquestion;
     private String pwanswer;
     private String motherlang;
     private Custcontact custcontact;

    public Customer() {
    }

	
    public Customer(int standid, short state, String nick, String password, String gender, String name, String firstname, String familystate, short active, String activationcode, String motherlang, Custcontact custcontact) {
        this.standid = standid;
        this.state = state;
        this.nick = nick;
        this.password = password;
        this.gender = gender;
        this.name = name;
        this.firstname = firstname;
        this.familystate = familystate;
        this.active = active;
        this.activationcode = activationcode;
        this.motherlang = motherlang;
        this.custcontact = custcontact;
    }
    public Customer(int standid, short state, String nick, String password, String gender, String name, String firstname, String birthname, String familystate, Date birthdate, String titel, short active, String activationcode, String pwquestion, String pwanswer, String motherlang, Custcontact custcontact) {
       this.standid = standid;
       this.state = state;
       this.nick = nick;
       this.password = password;
       this.gender = gender;
       this.name = name;
       this.firstname = firstname;
       this.birthname = birthname;
       this.familystate = familystate;
       this.birthdate = birthdate;
       this.titel = titel;
       this.active = active;
       this.activationcode = activationcode;
       this.pwquestion = pwquestion;
       this.pwanswer = pwanswer;
       this.motherlang = motherlang;
       this.custcontact = custcontact;
    }
   
    public Integer getId() {
        return this.id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    public int getStandid() {
        return this.standid;
    }
    
    public void setStandid(int standid) {
        this.standid = standid;
    }
    public short getState() {
        return this.state;
    }
    
    public void setState(short state) {
        this.state = state;
    }
    public String getNick() {
        return this.nick;
    }
    
    public void setNick(String nick) {
        this.nick = nick;
    }
    public String getPassword() {
        return this.password;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    public String getGender() {
        return this.gender;
    }
    
    public void setGender(String gender) {
        this.gender = gender;
    }
    public String getName() {
        return this.name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    public String getFirstname() {
        return this.firstname;
    }
    
    public void setFirstname(String firstname) {
        this.firstname = firstname;
    }
    public String getBirthname() {
        return this.birthname;
    }
    
    public void setBirthname(String birthname) {
        this.birthname = birthname;
    }
    public String getFamilystate() {
        return this.familystate;
    }
    
    public void setFamilystate(String familystate) {
        this.familystate = familystate;
    }
    public Date getBirthdate() {
        return this.birthdate;
    }
    
    public void setBirthdate(Date birthdate) {
        this.birthdate = birthdate;
    }
    public String getTitel() {
        return this.titel;
    }
    
    public void setTitel(String titel) {
        this.titel = titel;
    }
    public short getActive() {
        return this.active;
    }
    
    public void setActive(short active) {
        this.active = active;
    }
    public String getActivationcode() {
        return this.activationcode;
    }
    
    public void setActivationcode(String activationcode) {
        this.activationcode = activationcode;
    }
    public String getPwquestion() {
        return this.pwquestion;
    }
    
    public void setPwquestion(String pwquestion) {
        this.pwquestion = pwquestion;
    }
    public String getPwanswer() {
        return this.pwanswer;
    }
    
    public void setPwanswer(String pwanswer) {
        this.pwanswer = pwanswer;
    }
    public String getMotherlang() {
        return this.motherlang;
    }
    
    public void setMotherlang(String motherlang) {
        this.motherlang = motherlang;
    }
    public Custcontact getCustcontact() {
        return this.custcontact;
    }
    
    public void setCustcontact(Custcontact custcontact) {
        this.custcontact = custcontact;
    }
}

Das Hibernate Mapping für Customer
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
    
<hibernate-mapping>
<!-- 
    Created by the Middlegen Hibernate plugin 2.1

    http://boss.bekk.no/boss/middlegen/
    http://www.hibernate.org/
-->

<class 
    name="de.nfranze.sf.model.Customer" 
    table="customer"
>

    <id
        name="id"
        type="java.lang.Integer"
        column="id"
    >
        <generator class="native" />
    </id>

    <property
        name="standid"
        type="int"
        column="standid"
        not-null="true"
        length="10"
    />
    <property
        name="state"
        type="short"
        column="state"
        not-null="true"
        length="10"
    />
    <property
        name="nick"
        type="java.lang.String"
        column="nick"
        not-null="true"
        length="40"
    />
    <property
        name="password"
        type="java.lang.String"
        column="password"
        not-null="true"
        length="20"
    />
    <property
        name="gender"
        type="java.lang.String"
        column="gender"
        not-null="true"
        length="10"
    />
    <property
        name="name"
        type="java.lang.String"
        column="name"
        not-null="true"
        length="50"
    />
    <property
        name="firstname"
        type="java.lang.String"
        column="firstname"
        not-null="true"
        length="40"
    />
    <property
        name="birthname"
        type="java.lang.String"
        column="birthname"
        length="50"
    />
    <property
        name="familystate"
        type="java.lang.String"
        column="familystate"
        not-null="true"
        length="10"
    />
    <property
        name="birthdate"
        type="java.sql.Date"
        column="birthdate"
        length="10"
    />
    <property
        name="titel"
        type="java.lang.String"
        column="titel"
        length="10"
    />
    <property
        name="active"
        type="short"
        column="active"
        not-null="true"
        length="10"
    />
    <property
        name="activationcode"
        type="java.lang.String"
        column="activationcode"
        not-null="true"
        length="36"
    />
    <property
        name="pwquestion"
        type="java.lang.String"
        column="pwquestion"
        length="100"
    />
    <property
        name="pwanswer"
        type="java.lang.String"
        column="pwanswer"
        length="50"
    />
    <property
        name="motherlang"
        type="java.lang.String"
        column="motherlang"
        not-null="true"
        length="45"
    />

    <!-- Associations -->
  
    <!-- bi-directional one-to-one association to Custcontact -->
    <one-to-one
        name="custcontact"
        class="de.nfranze.sf.model.Custcontact"
        outer-join="auto"
        constrained="true"
    />

</class>
</hibernate-mapping>

Der CustomerContact (CustContact)
Code:
package de.nfranze.sf.model;
// Generated 20.03.2007 13:44:12 by Hibernate Tools 3.2.0.b9



/**
 * Custcontact generated by hbm2java
 */
public class Custcontact  implements java.io.Serializable {


     private Integer id;
     private String phone;
     private String fax;
     private String mail;
     private String mobile;
     private Customer customer;

    public Custcontact() {
    }

	
    public Custcontact(String mobile) {
        this.mobile = mobile;
    }
    public Custcontact(String phone, String fax, String mail, String mobile, Customer customer) {
       this.phone = phone;
       this.fax = fax;
       this.mail = mail;
       this.mobile = mobile;
       this.customer = customer;
    }
   
    public Integer getId() {
        return this.id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    public String getPhone() {
        return this.phone;
    }
    
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public String getFax() {
        return this.fax;
    }
    
    public void setFax(String fax) {
        this.fax = fax;
    }
    public String getMail() {
        return this.mail;
    }
    
    public void setMail(String mail) {
        this.mail = mail;
    }
    public String getMobile() {
        return this.mobile;
    }
    
    public void setMobile(String mobile) {
        this.mobile = mobile;
    }
    public Customer getCustomer() {
        return this.customer;
    }
    
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
}

Das Hibernate Mapping für Custcontact
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" >
    
<hibernate-mapping>
<!-- 
    Created by the Middlegen Hibernate plugin 2.1

    http://boss.bekk.no/boss/middlegen/
    http://www.hibernate.org/
-->

<class 
    name="de.nfranze.sf.model.Custcontact" 
    table="custcontact"
>

    <id
        name="id"
        type="java.lang.Integer"
        column="id"
    >
        <generator class="native" />
    </id>

    <property
        name="phone"
        type="java.lang.String"
        column="phone"
        length="40"
    />
    <property
        name="fax"
        type="java.lang.String"
        column="fax"
        length="40"
    />
    <property
        name="mail"
        type="java.lang.String"
        column="mail"
        length="40"
    />
    <property
        name="mobile"
        type="java.lang.String"
        column="mobile"
        not-null="true"
        length="45"
    />

    <!-- Associations -->
  
    <!-- bi-directional one-to-one association to Customer -->
    <one-to-one
        name="customer"
        class="de.nfranze.sf.model.Customer"
        outer-join="auto"
    />

</class>
</hibernate-mapping>

Das ICustomerManager
Code:
package de.nfranze.sf.logic.manager; //package de.nfranze.sf.model;
// Generated 20.03.2007 13:44:16 by Hibernate Tools 3.2.0.b9

/**
 * Home object for domain model class Customer.
 * @see de.nfranze.sf.model.Customer
 * @author Hibernate Tools
 */
  import java.util.List;
  import de.nfranze.sf.model.Customer;
  import javax.servlet.http.HttpServletRequest;

// TODO all methods should check if there is a result
// to prevent exceptions
public interface ICustomerManager
{
	public void Create(Customer model);
	
	public boolean IsIdentNoValid(String part1, int part2, String part3, String verification);
	public List<Customer> GetAll();
	public Customer GetByID(int id);
	
	public void Update(Customer model);
	public void Delete(int id);

}

Die Implementierung zum Manager
Code:
package de.nfranze.sf.logic.manager; //package de.nfranze.sf.model;
// Generated 20.03.2007 13:44:16 by Hibernate Tools 3.2.0.b9

/**
 * Home object for domain model class Customer.
 * @see de.nfranze.sf.model.Customer
 * @author Hibernate Tools
 */
 
 import java.util.List;
 import de.nfranze.sf.model.Customer;
 import de.nfranze.sf.logic.dao.ICustomerDAO;
 import javax.servlet.http.HttpServletRequest;
 
// TODO all methods should check if there is a result
// to prevent exceptions
public class CustomerManager implements ICustomerManager
{
	private ICustomerDAO m_customerDAO;
	public CustomerManager(ICustomerDAO dao)	{
		m_customerDAO=dao;	
	}
	
	public void Create(Customer model) {
		m_customerDAO.Save(model);
	}
	public boolean IsIdentNoValid(String part1, int part2, String part3, String verification)
	{
		return m_customerDAO.IsIdentNoValid(part1, part2, part3, verification);
	}
	public List<Customer> GetAll()
	{
		return m_customerDAO.GetAll();
	}
	public Customer GetByID(int id)
	{
		return m_customerDAO.GetByID(id);	
	}

	public void Update(Customer model) {
		m_customerDAO.Save(model);	
	}	
	
	public void Delete(int id) {
		m_customerDAO.Delete(id);	
	}	
}

Das ICustomerDAO
Code:
package de.nfranze.sf.logic.dao; //package de.nfranze.sf.model;
// Generated 20.03.2007 13:44:15 by Hibernate Tools 3.2.0.b9

import java.util.List;
import javax.servlet.http.HttpServletRequest;

/**
 * Home object for domain model class Customer.
 * @see de.nfranze.sf.model.Customer
 * @author Hibernate Tools
 */
 import de.nfranze.sf.model.Customer;
 
// TODO all methods should check if there is a result
// to prevent exceptions
public interface ICustomerDAO
{

	public List<Customer> GetAll() ;
	public Customer GetByID(int id);
	public boolean IsIdentNoValid(String part1, int part2, String part3, String verification);
	
	public void Save(Customer entity);
	public void Delete(int id);
}

Die Implementierung dazu
Code:
package de.nfranze.sf.logic.dao; //package de.nfranze.sf.model;
// Generated 20.03.2007 13:44:15 by Hibernate Tools 3.2.0.b9

import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;

import org.hibernate.criterion.Order;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.web.servlet.support.RequestContextUtils;


import de.nfranze.sf.model.Customer;
/**
 * Home object for domain model class Customer.
 * @see de.nfranze.sf.model.Customer
 * @author Hibernate Tools
 */
 
// TODO all methods should check if there is a result
// to prevent exceptions
public class CustomerDAO extends HibernateDaoSupport implements ICustomerDAO 
{

	public List<Customer> GetAll() {
		return getSession().createCriteria(Customer.class).addOrder(Order.asc("id")).list();
	}

	public Customer GetByID(int id) {
		return (Customer)getSession().createCriteria(Customer.class).add(Restrictions.idEq(id)).uniqueResult();
	}
	
	public boolean IsIdentNoValid(String part1, int part2, String part3, String verification)
	{
		return true;
	}
	public void Save(Customer entity) {
		getHibernateTemplate().saveOrUpdate(entity);
	}
	
	public void Delete(int id) {
		getHibernateTemplate().delete(GetByID(id));
	}
}

Die Spring xml-Konfigurationsdateien sind gesplittet, weil das so viel Zeug war. Ich hab eine Datei für DAOs, eine für Manager, eine web.xml und eine SpringDispatcher-servlet.xml. Ich poste nur die relevanten Teile.

ApplicationContext-dao.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
	<!-- Datenbankeinstellungen -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://fileserver/sf</value>
		</property>
		<property name="username" value="root"/>
		<property name="password" value="root"/>
	</bean>
	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="mappingDirectoryLocations">
			<list>
				<value>WEB-INF/src/de/nfranze/sf/model</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.cache">true</prop>
				<prop key="hibernate.cache.use_query_cache">false</prop>
			</props>
		</property>
	</bean>
	<!-- Weist Hibernate an, einen Transaktionsmanager zu nutzen -->
	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<!-- Die Klasse wird instantiiert mit dem Konstruktorargument SessionFactory (Daten für Datenbank)-->
		<!--  <constructor-arg ref="sessionFactory"/>-->
		<property name="sessionFactory">
			<ref local="sessionFactory"/>
		</property>
	</bean>

	<bean id="OpenSessionInViewFilter" class="org.springframework.orm.hibernate3.support.OpenSessionInViewFilter">
		<!-- <property name="sessionFactory" value="mySessionFactory"/>	
		<property name="sessionFactory">
            <ref local="sessionFactory"/>
        </property> -->
		<property name="singleSession" value="true"/>
	</bean>
	<bean id="hibernateDaoSupport" 
				class="org.springframework.orm.hibernate3.support.HibernateDaoSupport"
				abstract="true">
		<property name="sessionFactory">
			<ref bean="sessionFactory"/>
		</property>
	</bean>

	<bean id="customerDAO" class="de.nfranze.sf.logic.dao.CustomerDAO">
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>

Applicationcontext-manager.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
	<!-- This is the base transaction proxy factory bean, all transactional managers 
         use this bean definition. -->
	<bean id="txProxyTemplate" abstract="true"
			class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
		<property name="transactionAttributes">
			<props>
				<prop key="save*">PROPAGATION_REQUIRED</prop>
				<prop key="store*">PROPAGATION_REQUIRED</prop>
				<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
				<prop key="Get*">PROPAGATION_REQUIRED,readOnly</prop>
				<prop key="read*">PROPAGATION_REQUIRED,readOnly</prop>
				<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
				<prop key="*">PROPAGATION_REQUIRED</prop>
			</props>
		</property>

		<property name="preInterceptors">
			<list>

			</list>
		</property>

		<property name="postInterceptors">
			<list>

			</list>
		</property>
	</bean>

	<bean id="customerManager"  parent="txProxyTemplate">
		<property name="proxyInterfaces" value="de.nfranze.sf.logic.manager.ICustomerManager"/>
		<property name="target">
			<bean class="de.nfranze.sf.logic.manager.CustomerManager">
				<constructor-arg type="de.nfranze.sf.logic.dao.ICustomerDAO" ref="customerDAO"/>
			</bean>
		</property>
	</bean>

Die Datenbank. Da sind sehr viele Spalten, die eigentlich uninteressant sind, aber ich poste mal vorsichtshalber lieber alle...
Code:
DROP TABLE IF EXISTS `sf`.`customer`;
CREATE TABLE `customer` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `standid` int(10) unsigned NOT NULL,
  `state` int(10) unsigned NOT NULL,
  `nick` varchar(40) NOT NULL,
  `password` varchar(20) NOT NULL,
  `gender` int(10) unsigned NOT NULL,
  `name` varchar(50) NOT NULL,
  `firstname` varchar(40) NOT NULL,
  `birthname` varchar(50) default NULL,
  `familystate` int(10) unsigned NOT NULL,
  `birthdate` date default NULL,
  `titel` int(10) unsigned default NULL,
  `active` int(10) unsigned NOT NULL,
  `activationcode` varchar(36) NOT NULL,
  `pwquestion` varchar(100) default NULL,
  `pwanswer` varchar(50) default NULL,
  `motherlang` varchar(45) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='InnoDB free: 10240 kB; InnoDB free: 10240 kB; (`id`) REFER `';

DROP TABLE IF EXISTS `sf`.`custcontact`;
CREATE TABLE `custcontact` (
  `id` int(10) unsigned NOT NULL default '0',
  `phone` varchar(40) default NULL,
  `fax` varchar(40) default NULL,
  `mail` varchar(40) default NULL,
  `mobile` varchar(45) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Das Beispiel (wird im RegisterWizard ausgeführt):
Code:
    	Customer customer=new Customer();
   	customer.setNick(NullOrEmpty(register.getNick()));
    	customer.setPassword(NullOrEmpty(register.getPassword()));
  
       	customer.setPwquestion(NullOrEmpty(register.getPwQuestion()));
       	customer.setPwanswer(NullOrEmpty(register.getAnswer()));
    	
       	customer.setName(NullOrEmpty(register.getName()));
       	customer.setFirstname(NullOrEmpty(register.getFirstName()));
       	
       	// setzen aller weiteren Felder von customer, die nicht null sein dürfen


      	 customer.setCustcontact(new Custcontact());
      	
     	customer.getCustcontact().setMail(NullOrEmpty(register.getEmail()));
      	customer.getCustcontact().setMobile(NullOrEmpty(register.getMobile()));

		ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());

		ICustomerManager customerManager = (ICustomerManager)context.getBean("customerManager");

       	customerManager.Create(customer);

Die Funktion NullOrEmpty gibt lediglich "" zurück, falls der übergebene String null sein sollte. In register stehen alle Eingaben drin, die man während des Registrierenvorgangs machen kann. Das klappt auch alles soweit.
So, das ist alles. und bei customerManager.Create(customer); bekomm ich eine ConstraintViolationException.
Was mach ich falsch?
 

Neue Beiträge

Zurück