Hello,
This is the part 2 of the series about working with maven, spring, and hibernate together. We will use mysql, hibenate,jpa, spring-data-jpa in netbeans.
Before we start, i will like us to be on the same page so , we will create a database for our project, its user and credentials.
- Let’s connect to mysql database
$ mysql -uroot -p #at the prompt enter your root password
mysql> create database family; Query OK, 1 row affected (0.00 sec)
mysql> GRANT ALL PRIVILEGES ON family.* TO 'shizune'@'localhost' IDENTIFIED BY 'tonton'; Query OK, 0 rows affected (0.05 sec)
mysql> FLUSH PRIVILEGES; Query OK, 0 rows affected (0.01 sec)
- Locate Other Test Sources in projects tab
- Right Click: src/test/resources > Properties File
- Name the file: mysql.jdbc.properties
#MySQL JDBC Props jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.username=shizune jdbc.password=tonton jdbc.url=jdbc:mysql://localhost:3306/family
- Locate Other Test Sources in projects tab
- Right Click: src/test/resources > Properties File
- Name the file: mysql.hibernate.properties
#MySQL Hibernate Props hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true hibernate.format_sql=true hibernate.hbm2ddl.auto=create
Notes :
Because of Netbeans support for certain technologies like persistence or spring, using netbeans way of adding any of these files doesn’t play so well. Apparently Netbeans forces it ways by generating some of files and even adding some dependencies to the classpath regardless of whether is the another version declared in the pom or not. Best way i have found is to create a simple xml file as opposed to use Netbeans.
- Right Click: src/main/resources > New Folder
- name the folder: META-INF
- Right Click: META-INF > New File > Xml Document
- Name the document : persistence.xml > Next > choose well-formed document
<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="family" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> </persistence-unit> </persistence>
In this tutorial, we will use spring application context per concern, I mean by that, using an application context for database connectivity only and for nothing else.
- Right Click: src/test/resources > New Folder
- name the folder: META-INF
- Right Click: META-INF > New File > Xml Document
- Name the document : testing-db-config.xml > Next > choose well-formed document
<?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:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang" xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd http://www.springframework.org/schema/tx"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:mysql.hibernate.properties</value> <value>classpath:mysql.jdbc.properties</value> </list> </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 id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="net.djomeda.tutorials.springdatamvcfamily.model"/> <property name="persistenceUnitName" value="family" /> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> <prop key="hibernate.format_sql">${hibernate.format_sql}</prop> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop> </props> </property> </bean> <bean id="jpdDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/> <jpa:repositories base-package="net.djomeda.tuturialsspringdatamvcfamily.repository"/> </beans>
Creating Models
For now we will create Family, Person and Profile models without any relationship between them and then build the relations bit by bit. We will create them in net.djomeda.tutorials.springdatamvcfamily.model package.
Person Model
package net.djomeda.tutorials.springdatamvcfamily.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; /** * * @author joseph */ @Entity @Table(name = "person") public class Person { @Id @Column(name = "person_id") private String ID; @Column(name = "name") private String name; @Column(name = "age") private String age; @Column(name = "gender") private String gender; /** * @return the ID */ public String getID() { return ID; } /** * @param ID the ID to set */ public void setID(String 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 age */ public String getAge() { return age; } /** * @param age the age to set */ public void setAge(String age) { this.age = age; } /** * @return the gender */ public String getGender() { return gender; } /** * @param gender the gender to set */ public void setGender(String gender) { this.gender = gender; } }
Family Model
package net.djomeda.tutorials.springdatamvcfamily.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; /** * * @author joseph */ @Entity @Table(name = "family") public class Family { @Id @Column(name = "family_id") private String ID; @Column(name = "name") private String name; @Column(name = "tribe") private String tribe; @Column(name = "description") private String description; /** * @return the ID */ public String getID() { return ID; } /** * @param ID the ID to set */ public void setID(String 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 tribe */ public String getTribe() { return tribe; } /** * @param tribe the tribe to set */ public void setTribe(String tribe) { this.tribe = tribe; } /** * @return the description */ public String getDescription() { return description; } /** * @param description the description to set */ public void setDescription(String description) { this.description = description; } }
Profile Model
package net.djomeda.tutorials.springdatamvcfamily.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; /** * * @author joseph */ @Entity @Table(name = "profile") public class Profile { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int ID; @Column(name = "favorite_hobby") private String favoriteHobby; @Column(name = "averageGradeInSchool") private String averageGradeInSchool; /** * @return the ID */ public int getID() { return ID; } /** * @param ID the ID to set */ public void setID(int ID) { this.ID = ID; } /** * @return the favoriteHobby */ public String getFavoriteHobby() { return favoriteHobby; } /** * @param favoriteHobby the favoriteHobby to set */ public void setFavoriteHobby(String favoriteHobby) { this.favoriteHobby = favoriteHobby; } /** * @return the averageGradeInSchool */ public String getAverageGradeInSchool() { return averageGradeInSchool; } /** * @param averageGradeInSchool the averageGradeInSchool to set */ public void setAverageGradeInSchool(String averageGradeInSchool) { this.averageGradeInSchool = averageGradeInSchool; } }
Let’s create a dummy test class to trigger the generation of our tables in the database
package net.djomeda.tutorials.springdatamvcfamily.model; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * * @author joseph */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:META-INF/testing-db-config.xml") public class FamilyTest { public FamilyTest() { } @Test public void GenerateDatabaseTest(){ Assert.assertTrue(true); } }
If all the files and configurations are done properly the test will succeed and thus generating 3 Tables in the database.
Mapping Models Relationships
Linking Family to Person in a OneToMany relationsship
//private String description; is above @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true,mappedBy="family") private Set<Person> familyMembers = new HashSet<Person>();
Linking Person to Family making the ManyToOne side of the relationship. Now because Person object knows about Family our relationship becomes bi-directional. Append the following to Person.java class after gender property.
@ManyToOne @JoinColumn(name = "family_id") private Family family;
Linking Person to Profile in a OneToOne relationship. This is an example of unidirectional relationship where Profile object doesn’t know about its owner Person class
// private Family family is above @OneToOne(cascade = CascadeType.ALL) @JoinColumn(name = "profile") private Profile profile;
Creating Spring-Data-Jpa repositories
FamilyRepository
package net.djomeda.tutorials.springdatamvcfamily.repository; import net.djomeda.tutorials.springdatamvcfamily.model.Family; import org.springframework.data.jpa.repository.JpaRepository; /** * * @author joseph */ public interface FamilyRepository extends JpaRepository<Family, String> { }
PersonRepository
package net.djomeda.tutorials.springdatamvcfamily.repository; import net.djomeda.tutorials.springdatamvcfamily.model.Person; import org.springframework.data.jpa.repository.JpaRepository; /** * * @author joseph */ public interface PersonRepository extends JpaRepository<Person, String> { }
ProfileRepository
package net.djomeda.tutorials.springdatamvcfamily.repository; import net.djomeda.tutorials.springdatamvcfamily.model.Profile; import org.springframework.data.jpa.repository.JpaRepository; /** * * @author joseph */ public interface ProfileRepository extends JpaRepository<Profile, Integer>{ }
Voila! we have a very capable data layer set with spring-data-jpa. Next we will see how to use it in a web application the MVC controllers and views