Java >> Java tutorial >  >> Tag >> XML

Dvale en-til-en-forhold eksempel (XML-kortlægning og annotering)

I dette eksempel skal vi se, hvordan man kortlægger klasser til databasetabeller, som har en-til-en-relationer. Vi kommer til at se kortlægningen både med XML Mapping og med Annotations.

Så disse er værktøjerne, vi skal bruge på en Windows 7-platform:

  • JDK 1.7
  • Maven 3.0.5
  • Dvaletilstand 3.6.3.Final
  • MySQL JDBC-driver 5.1.9
  • Eclipse 4.2 Juno

Kortlægning af klasserne ved hjælp af XML Mapping

1. Download projektet fra den forrige selvstudie

Tag et nærmere kig på Hibernate 3 med Maven 2 og MySQL 5 Eksempel (XML Mapping and Annotation) tutorial for at lære, hvordan man opretter et projekt med Maven og for at skabe den grundlæggende struktur i projektet. Det er det projekt, vi skal bruge her. Så følg trinene for at oprette projektet.

Sørg for, at projektstrukturen ser sådan ud:

2. En-til-en-forhold

Forestil dig, at du har tabel A og B i en database. Hver tupel i A indeholder grundlæggende information om enheder. Og vi vil have en anden, større tabel B, der rummer alle de oplysninger, vi skal opbevare om hver enhed, der er optaget i A. Så dette er den grundlæggende strategi, du skal følge for at samle tabellerne i databasen:

DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `STUDENT_ID` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `STUDENT_NAME` VARCHAR(10) NOT NULL,
  `STUDENT_AGE` VARCHAR(20) NOT NULL,
  PRIMARY KEY (`STUDENT_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `student_information`;
CREATE TABLE  `student_information` (
 `STUDENT_ID` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
 `ADDRESS` VARCHAR(100) NOT NULL,
 `REGISTRY_NUMBER` VARCHAR(255),
 `PHONE_NUMBER` VARCHAR(255),
 `ENLISTED` DATE NOT NULL,
 PRIMARY KEY (`STUDENT_ID`) ,
 CONSTRAINT `FK_STUDENT_ID` FOREIGN KEY (`STUDENT_ID`) REFERENCES `student` (`STUDENT_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

Dette er et simpelt diagram over tabellerne, der viser dette forhold, skabt med MySQL Workbech (som jeg personligt holder meget af).

Som du kan se "student_information ” indeholder “STUDENT_ID ", som er den primære nøgle (og derfor identifikatoren) af "student " bord. "STUDENT_ID ” er også den primære nøgle til “student_information “, men det er en fremmednøgle til “student ” også bordet. Og det er det, der forbandt disse tabeller med en-til-en-forholdet. Det betyder, at for hver elev tuples i "student ”-tabellen, vil der kun være én tilsvarende tuple i “student_information ”.

3. Rediger pom.xml

Sørg for, at pom.xml indeholder disse afhængigheder:

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.javacodegeeks.enterprise.hibernate</groupId>
  <artifactId>HibernateMySQLExample</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>HibernateMySQLExample</name>
  <url>http://maven.apache.org</url>
  <!-- JBoss repository for Hibernate -->
	<repositories>
		<repository>
			<id>JBoss repository</id>
			<url>http://repository.jboss.org/nexus/content/groups/public/</url>
		</repository>
	</repositories>

	<dependencies>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.8.2</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>1.7.0</version>
			<scope>runtime</scope>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>1.7.0</version>
			<scope>runtime</scope>
		</dependency>

		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>1.7.0</version>
			<scope>runtime</scope>
		</dependency>

		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.14</version>
		</dependency>

		<!-- MySQL database driver -->

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.9</version>
		</dependency>

		<!-- Hibernate framework -->

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>3.6.3.Final</version>
		</dependency>

		<dependency>
			<groupId>javassist</groupId>
			<artifactId>javassist</artifactId>
			<version>3.12.1.GA</version>
		</dependency>

	</dependencies>

</project>

3. Opret klasserne

Så disse er de klasser, der vil blive knyttet til databasetabeller:

Du skal opdatere Student.java fil til denne:

Student.java:

package com.javacodegeeks.enterprise.hibernate;

public class Student implements java.io.Serializable {

	private static final long serialVersionUID = 1L;

	private Integer studentId;
	private String  studentName;
	private String  studentAge;
	private StudentInformation studentInfo;

	public Student() {
	}

	public Student(String studentName, String studentAge) {
		this.studentName = studentName;
		this.studentAge = studentAge;
	}

	public Integer getStudentId() {
		return this.studentId;
	}

	public void setStudentId(Integer studentId) {
		this.studentId = studentId;
	}

	public String getStudentName() {
		return this.studentName;
	}

	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}

	public String getStudentAge() {
		return this.studentAge;
	}

	public void setStudentAge(String studentAge) {
		this.studentAge = studentAge;
	}

	public StudentInformation getStudentInfo() {
		return studentInfo;
	}

	public void setStudentInfo(StudentInformation studentInfo) {
		this.studentInfo = studentInfo;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}

}

Ovenstående klasse vil naturligvis blive kortlagt til "student " bord. Bemærk, at Student klasse har en StudentInformation eksempel.

Nu skal du oprette en ny StudentInformation klasse. Gå til Pakkeopdageren og find hovedkildepakken til vores projekt:

Højreklik -> Ny -> Klasse:

StudentInformation.java:

package com.javacodegeeks.enterprise.hibernate;

import java.util.Date;

public class StudentInformation {

	private Integer studentId;
	private String address;
	private String registryNumber;
	private String phoneNumber;
	private Date enlisted;

	private Student student;

	public Integer getStudentId() {
		return studentId;
	}

	public void setStudentId(Integer studentId) {
		this.studentId = studentId;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getRegistryNumber() {
		return registryNumber;
	}

	public void setRegistryNumber(String registryNumber) {
		this.registryNumber = registryNumber;
	}

	public String getPhoneNumber() {
		return phoneNumber;
	}

	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	public Date getEnlisted() {
		return enlisted;
	}

	public void setEnlisted(Date enlisted) {
		this.enlisted = enlisted;
	}

	public Student getStudent() {
		return student;
	}

	public void setStudent(Student student) {
		this.student = student;
	}
}

Bemærk, at ovenstående klasse har en Student eksempel.

4. XML-kortlægningsfiler

Gå til /src/main/resources/com/javacodegeeks/enterprise/hibernate mappe og opret følgende xml-filer:

Student.hbm.xml:

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

<hibernate-mapping>
    <class name="com.javacodegeeks.enterprise.hibernate.Student" table="student" catalog="tutorials">
        <id name="studentId" type="java.lang.Integer">
            <column name="STUDENT_ID" />
            <generator class="identity" />
        </id>
        <property name="studentName" type="string">
            <column name="STUDENT_NAME" length="10" not-null="true" unique="true" />
        </property>
        <property name="studentAge" type="string">
            <column name="STUDENT_Age" length="20" not-null="true" unique="true" />
        </property>

        <one-to-one name="studentInfo" class="com.javacodegeeks.enterprise.hibernate.StudentInformation"
			cascade="save-update"></one-to-one>
    </class>
</hibernate-mapping>

Den interessante bit her er:

<one-to-one name="studentInfo" class="com.javacodegeeks.enterprise.hibernate.StudentInformation"cascade="save-update">
</one-to-one>

hvor vi beskriver, at studentInfo klassens attribut har en en-til-en relation med StudentInformation . Vi angiver også, at når student tabellen er opdateret, skal opdateringen kaskades til student_information bord.

StudentInformation.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 25 April 2011 7:52:33 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
	<class name="com.javacodegeeks.enterprise.hibernate.StudentInformation" table="student_information" 	catalog="tutorials">
		<id name="studentId" type="java.lang.Integer">
			<column name="STUDENT_ID" />
			<generator class="foreign">
				<param name="property">student</param>
			</generator>
		</id>

		<property name="address" type="string">
			<column name="ADDRESS" length="100" not-null="true" />
		</property>
		<property name="registryNumber" type="string">
			<column name="REGISTRY_NUMBER" length="255"  />
		</property>
		<property name="phoneNumber" type="string">
			<column name="PHONE_NUMBER" length="255" />
		</property>
		<property name="enlisted" type="date">
			<column name="ENLISTED" length="10" not-null="true" />
		</property>

		<one-to-one name="student" class="com.javacodegeeks.enterprise.hibernate.Student"
			constrained="true"></one-to-one>
	</class>
</hibernate-mapping>

Igen, her er den interessante del:

<id name="studentId" type="java.lang.Integer">
<column name="STUDENT_ID" />
	<generator class="foreign">
		<param name="property">student</param>
	</generator>
</id>

Her angiver vi, at studentId attribut for StudentInformation klasse er en "fremmednøgle" til student klassens egenskab. Dette forhold afspejles også i de tilsvarende databasetabeller.

5. Opdater Hibernate-konfigurationsfil:

Gå til pakkeudforskeren og find hibernate.cfg.xml fil og indsæt følgende kode:

hibernate.cfg.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password"></property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/tutorials</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="show_sql">true</property>
		<mapping resource="com/javacodegeeks/enterprise/hibernate/Student.hbm.xml"></mapping>
		<mapping resource="com/javacodegeeks/enterprise/hibernate/StudentInformation.hbm.xml"></mapping>
	</session-factory>
</hibernate-configuration>

Dette er stort set det samme som den forrige tutorial. Vi tilføjede simpelthen kortlægningsrelationerne for de to klasser.

6. Kod applikationen.

Gå til filen App.java og indsæt følgende kode:

App.java:

package com.javacodegeeks.enterprise.hibernate;

import java.util.Date;

import org.hibernate.Session;
import com.javacodegeeks.enterprise.hibernate.utils.HibernateUtil;;

public class App 
{
    public static void main( String[] args )
    {
        Session session = HibernateUtil.getSessionFactory().openSession();

        session.beginTransaction();
        Student student = new Student();

        student.setStudentName("JavaFun");
        student.setStudentAge("19");

        StudentInformation studentInfo = new StudentInformation();

        studentInfo.setAddress("1st Street");
        studentInfo.setPhoneNumber("982349823");
        studentInfo.setRegistryNumber("ax203");
        studentInfo.setEnlisted(new Date());

        studentInfo.setStudent(student);
        student.setStudentInfo(studentInfo);

        session.save(student);
        session.getTransaction().commit();
        System.out.println("Great! Student was saved");
    }
}

Ovenstående kode har nogle bemærkelsesværdige dele. Først og fremmest får vi en Session fra SessionFactory forekomst af vores HibernateUtils klasse. Så starter vi en transaktion med databasen. Vi opretter simpelthen en forekomst af hver klasse, og vi tildeler hver enkelt den tilsvarende egenskab for den anden. Derefter gemmer vi til Session kun student instans og endelig begå transaktionen. Som du kan se, indsætter vi en ny student hver gang tuple, automatisk en ny student_information tuple vil blive indsat. Ved transaktionsbekræftelse tømmes/synkroniseres Hibernate-sessionen med databasen. Så den nyoprettede Student-forekomst, der findes i sessionen, bevares i databasen.

7. Kør programmet

Dette er output fra programmet:

log4j:WARN No appenders could be found for logger (org.hibernate.type.BasicTypeRegistry).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into tutorials.student (STUDENT_NAME, STUDENT_Age) values (?, ?)
Hibernate: insert into tutorials.student_information (ADDRESS, REGISTRY_NUMBER, PHONE_NUMBER, ENLISTED, STUDENT_ID) values (?, ?, ?, ?, ?)
Great! Student was saved

Dette var et eksempel på Hibernate One-to-One Relationship Eksempel ved hjælp af XML Mapping. Download Eclipse-projektet i denne del:Hibernate1to1XMLExample.zip

Kortlægning af klasserne ved hjælp af annoteringer

Til denne del skal vi bare lave nogle opdateringer til det tidligere projekt. Den største forskel er, at vi ikke kommer til at bruge Student.hbm.xml og StudentInformation.hbm.xml at kortlægge klasserne til de tilsvarende tabeller i databasen. Vi vil bruge specielle anmærkninger i java klasser, der vil diktere kortlægningen.

1. Slet Student.hbm.xml og StudentInformation.hbm.xml

Vi har ikke brug for dem mere.

2. Opdater pom.xml fil for at inkludere Hibernate Annotation-bibliotek

Siden Hibernate version 3.6 er annotationsrammerne inkluderet i hibernate-core.jar-modulet, så ingen opdatering for os.

Men hvis du støder på problemer, skal du opdatere pom.xml fil for også at inkludere disse biblioteker:

<dependency>
	<groupId>hibernate-annotations</groupId>
	<artifactId>hibernate-annotations</artifactId>
	<version>3.6.3.Final</version>
</dependency>

<dependency>
	<groupId>hibernate-commons-annotations</groupId>
	<artifactId>hibernate-commons-annotations</artifactId>
	<version>3.6.3.Final</version>
</dependency>

Og kør derefter mvn eclipse:eclipse for at downloade de nødvendige krukker og opdatere klassestien til dit projekt.

3. Opdater klasserne for at inkludere dvaleannoteringer

Sådan er den kommenterede Student.java filen skal se sådan ud:

package com.javacodegeeks.enterprise.hibernate;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import static javax.persistence.GenerationType.IDENTITY;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "student", catalog = "tutorials")
public class Student implements java.io.Serializable {

	private static final long serialVersionUID = 1L;

	private Integer studentId;
	private String  studentName;
	private String  studentAge;
	private StudentInformation studentInfo;

	public Student() {
	}

	public Student(String studentName, String studentAge) {
		this.studentName = studentName;
		this.studentAge = studentAge;
	}

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "STUDENT_ID", unique = true, nullable = false)
	public Integer getStudentId() {
		return this.studentId;
	}

	public void setStudentId(Integer studentId) {
		this.studentId = studentId;
	}

	@Column(name = "STUDENT_NAME", nullable = false, length = 10)
	public String getStudentName() {
		return this.studentName;
	}

	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}

	@Column(name = "STUDENT_AGE", nullable = false, length = 20)
	public String getStudentAge() {
		return this.studentAge;
	}

	public void setStudentAge(String studentAge) {
		this.studentAge = studentAge;
	}

	@OneToOne(fetch = FetchType.LAZY, mappedBy = "student", cascade = CascadeType.ALL)
	public StudentInformation getStudentInfo() {
		return studentInfo;
	}

	public void setStudentInfo(StudentInformation studentInfo) {
		this.studentInfo = studentInfo;
	}

	public static long getSerialversionuid() {
		return serialVersionUID;
	}	
}

StudentInformation.java:

package com.javacodegeeks.enterprise.hibernate;

import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;

@Entity
@Table(name = "student_information", catalog = "tutorials")
public class StudentInformation {

	private Integer studentId;
	private String address;
	private String registryNumber;
	private String phoneNumber;
	private Date enlisted;

	private Student student;

	@GenericGenerator(name = "generator", strategy = "foreign", parameters = @Parameter(name = "property", value = "student"))
	@Id
	@GeneratedValue(generator = "generator")
	@Column(name = "STUDENT_ID", unique = true, nullable = false)
	public Integer getStudentId() {
		return studentId;
	}

	public void setStudentId(Integer studentId) {
		this.studentId = studentId;
	}

	@Column(name = "ADDRESS", nullable = false, length = 100)
	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	@Column(name = "REGISTRY_NUMBER", length = 255)
	public String getRegistryNumber() {
		return registryNumber;
	}

	public void setRegistryNumber(String registryNumber) {
		this.registryNumber = registryNumber;
	}

	@Column(name = "PHONE_NUMBER", length = 255)
	public String getPhoneNumber() {
		return phoneNumber;
	}

	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "ENLISTED", nullable = false)
	public Date getEnlisted() {
		return enlisted;
	}

	public void setEnlisted(Date enlisted) {
		this.enlisted = enlisted;
	}

	@OneToOne(fetch = FetchType.LAZY)
	@PrimaryKeyJoinColumn
	public Student getStudent() {
		return student;
	}

	public void setStudent(Student student) {
		this.student = student;
	}
}

Dette er de grundlæggende ting, du behøver at vide om Hibernate-annoteringer :

  • @Entity :bruges til at markere den specifikke klasse som en Hibenrate-entitetsklasse, der vil blive knyttet til en databasetabel.
  • @Table :bruges til at angive den databasetabel, som denne klasse er knyttet til. Hvis @Tabel annotering ikke er angivet, vil klassenavnet blive betragtet som tabelnavnet.
  • @Id :bruges til at specificere den attribut, der svarer til den primære nøgle i databasetabellen.
  • @GeneratedValue :bruges til at specificere den primære nøglegenereringsstrategi og bruges til automatisk genererede id'er (f.eks. automatisk stigning i dette eksempel).
  • @Column :bruges til at angive den kolonne, som et felt vil blive knyttet til. Hvis det ikke er angivet, vil attributnavnet og -typen blive betragtet som henholdsvis kolonnenavnet og -typen.
  • @OneToOne :bruges til at definere en en-til-en-relation med klassen for den specifikke attribut. fetch = FetchType.LAZY attribut er et hint til persistensudbyderens runtime om, at data skal hentes, når de først tilgås. Hvis der ikke er deklareret nogen hente-strategi, så bruges lazy som standard. På den anden side er EAGER-strategien et krav på persistensudbyderens runtime, at data skal være ficeret, når de bliver spurgt, og ikke kun, når de tilgås. Når vi har 2 sammenkædede tabeller, har kun 1 af disse tabeller en fremmednøglebegrænsning i forhold til den anden. mappedBy = "student" attributter angiver, at du stadig kan linke fra tabellen, der ikke indeholder fremmednøglen, til den anden tabel
  • @GenericGenerator :generatorannotation, der beskriver enhver form for Hibernate-generator på en detyperet måde. Strategien (i StudentInformation.java ) har værdien foreign fordi attributten er en fremmednøgle til student tabel
  • @Temporal :bruges til at betegne tidsmæssige typer, f.eks. datoer.
  • @PrimaryKeyJoinColumn :Definerer kortlægning for sammensatte fremmednøgler

4. Opdater Hibernate-konfigurationsfil

Gå til pakkeudforskeren og find hibernate.cfg.xml fil og indsæt følgende kode:

dvale.cfg.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
	<session-factory>
		<property name="hibernate.bytecode.use_reflection_optimizer">false</property>
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password"></property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/tutorials</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<property name="show_sql">true</property>
		<mapping class="com.javacodegeeks.enterprise.hibernate.Student"></mapping>
		<mapping class="com.javacodegeeks.enterprise.hibernate.StudentInformation"></mapping>
	</session-factory>
</hibernate-configuration>

5. Kør programmet

Du behøver ikke at ændre noget til App.java. Kør blot programmet.

Dette er output fra programmet:

log4j:WARN No appenders could be found for logger (org.hibernate.type.BasicTypeRegistry).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into tutorials.student (STUDENT_NAME, STUDENT_Age) values (?, ?)
Hibernate: insert into tutorials.student_information (ADDRESS, REGISTRY_NUMBER, PHONE_NUMBER, ENLISTED, STUDENT_ID) values (?, ?, ?, ?, ?)
Great! Student was saved

Dette var et eksempel på Dvale en-til-en-forholdseksempel ved hjælp af annoteringer. Download Eclipse-projektet i denne del:Hibernate1to1AnnotExample.zip

Java tag