Spring Data JPA & Spring 3 Transactions Through JTA and Atomikos
In this article I will discuss about Spring Transactions with JTA.
The underlying JTA implementation with Atomikos.
The server platform is jBoss7.
The XA-DataSource configured in jBoss AS7 is of the type Oracle 10g.
The Underlyimg Persistence Provider in Hibernate 4.
I have used the Hibernate Module already available with jBoass AS7, but during
Startup of my application I faced some issues for which i have to
Externally plug in the jar "hibernate-core-3.6.0.Final.jar", Tried to
find out the reason behind but remain undone.
Now before going into the discussion, I will first try note down the jars that
I have used, as this portion has Given me Immense pain due to
lack of proper Documentation.
jar List
---------------------------------
1) hibernate-core-3.6.0.Final.jar
2) transactions-jta-3.6.4.jar
3) atomikos-util-3.6.4.jar
4) transactions-3.6.4.jar
5) transactions-api-3.6.4.jar
6) transactions-hibernate3-3.6.4.jar
7) transactions-jdbc-3.6.4.jar
8) concurrent-1.3.4.jar
9) cglib-nodep-2.2.3.jar
--------------------------------
Now apart from the above mentioned jars, the jars required to up and run a
Spring application is also required to be taken care of.
Please note: Various custom JTA properties can be set through Atomikos with the help of a property file
known as jta.properties.
But I jave not used it as I have gone with the default properties.
If anybody wishes to use it Proper documentation is alreay there at Atomikos Site.
During Startup an error will crop p saying that the file jta.properties is
not available in the classpath, which can be ignored.
First I will discuss about the configuration part and the issues that I have faced.
Before going into the aforementioned details of the previously mentioned post, lets dive into
the Spring-Data-JPA and Spring-Data-Commons API which I have used for JPA implementation in Spring.
The basic Idea behind Spring-Data-JPA and Spring-Data-Commons implementation, is to keep aside all the boilerplate JPA
implementation code and provide a clean interface to the common DAO methods, in other
word we can say that we can bid goodbye on the DAO layer.
In addition to the common DAO methods which are provided by the API by default custom DATA methods as per
business requirements can be defined very easily without any added overhead, Not only this, another feature of
these api which seems to be very interesting to me is the JPA Criteria API.
The main catch behind this API is the java representation of any type of SQL query (Simple.... Complex.....)
any type. Further the Queries can be made type safe with Java MetaModel classes.
Metamodel classes represents the Domain classes (Entity classes... i.e. classes representing
tables in underlying databases) along with their state and relationship with the other Domain entities.
These metamodel classes can be generated very easily with the help of Ant Task.
All the above mentioned features, Which I have implemented at a very Basic level, with Custom
configuration which can be very helpful in Real Time projects will be Discussed next.
For Furthur Information and all the API related details Spring-Data-JPA and Spring-Data-Commons
documentation should be consulted. They are very much precise,accurate and easy to implement.
So lets, start Now.At the heart of the Spring-Data-JPA lies the Repository implementation,
which contains all the Data Manupulation workarounds.
I have implemented a Generic Repository interface which will be implemented by Domain Specific Repositories,
So that all the Data Access methods lies within the Repository and hence can be accessed from that, including Custom
methods if required.
A bit confusing......... So lets go with the examples to make things a bit Bright.
The Generic Repository used is:
(can be verified from the API documentation).
Here T represents the Domain Entity class and
ID represents the Primary Key (Simple or Composite) of the corresponding
Entity class.
The Custom method method for example which I have used here is:testCustomtoAllRepo()
The annotation @NoRepositoryBean has been used here so that no Repository
corresponding to this Bean should be generated by the API as this should be the Base
Repository all our Domain Entity Specific Repository.
This would become more clear as we Progress.
Lets us consider and Domain Entity Car.
So this is in Short the Repository skeleton Structure, and here is only the interfaces
where lies the implementation?
For Custom configuration we would provide the implementation to the interface
and the have API engine to generate the Implementation Bean object and use this object to
access the repository specific methods.
Again a bit confusing and believe me We will clarify it soon as progress.
The Implementation Bean is:
So, From the Implementation Class, things are Very little clear now.
Now How the API engine Knows that the Domain Specific Repository interface
would use this Implementation?????
This can be done through custom Factory Bean and Factory classes and these are configured
in Spring-jpa.xml i.e. configuration file.
The Factory Bean class is:
Generated the Factory and the Factory finally creates an object of the Repository Implmentation Bean.
Any Custom methods if required can be defined here and hence is avilable application wide.
Cool Isn't it.
For Spring Spring JPA we are using the JPA namespace in the configuration file.
The configuration related details are:
The base-package should contain all the domain Specific Repository.
entity-manager-factory-ref defines the entity amanger Factory to be used in the
Specific Repository Implementation.
and the factory-class is the Factory Bean implelemntation.
So till now things are little more clear.
Let me get all we have dicussed till Now through an example. which will clarify things more.
Lets us define a Service class containing domain specific Repository (CarRepository) REFERENCE.
The service classes beans are generated through auto detection thorough annotation and with the
help of component-scan base-package element as described in the above configuration,
i.e. all the service classes described in the package define in the component-scan base-package element.
The service class is:
@Service: This annotation describes this Bean to be a Service Layer Bean and registers the bean with the name as defined.
@Autowired
CarRepository carRepository: Spring DATA JPA Injects the proper implementation class (as DESCRIBED ABOVE) in the reference,
and with this reference we have preformed various methods, as evident from various methods.
So, till Now what we have dicussed, almost all the things are out of Shadow, regarding various Spring JPA Config and Usage.
So, the DAO layer are no more a requirement now, and we can thus proceed with Spring JPA.
Just Feel free to share any doubts with me, Just Post Your doubts...
I will try to answer ... and till then happy coding and feel the magic of Spring JPA and Spring DATA ;-)
It is really been long since I added up anything and I really apologize for that. Lets continue the above topic and bring it to conclusion.
Next interesting thing that I came across while going through Spring DATA JPA is the criteria API. In a single word it is the java representation of the SQL queries. Every bit of action that can be done through SQL queries is possible through it. This topic is really vast, lets feel some taste of it.
The first and foremost thing in CRITERIA API is the metamodel classes of Domain entity classes, which can be generated through a ANT task.
Say, The Domain entity class for CAR is:
<target name="CREATE-METAMODEL">
<copyfile dest="F:/My_prog/Spring Workspaces/SpringREST/AntLib" src="C:/Users/hcl/Desktop/Spring Related/hibernate-jpamodelgen-1.3.0.Final-dist/hibernate-jpamodelgen-1.3.0.Final/hibernate-jpamodelgen-1.3.0.Final.jar"/>
<javac srcdir="${src}/com/springRest/domainEntity" destdir="${src}/metamodel" failonerror="false" fork="true">
<classpath refid="classpath"/>
<compilerarg value="-proc:only"/>
</javac>
Now using criteria query we are going to query for all cars having owners.
The foreign key in Car_Owner is id of Car.
The car details are encapsulated in custom java bean "CarDesc".
This is in very short a glimpse of the Criteria API, please go through its documentation , It's really nice and interesting.
The underlying JTA implementation with Atomikos.
The server platform is jBoss7.
The XA-DataSource configured in jBoss AS7 is of the type Oracle 10g.
The Underlyimg Persistence Provider in Hibernate 4.
I have used the Hibernate Module already available with jBoass AS7, but during
Startup of my application I faced some issues for which i have to
Externally plug in the jar "hibernate-core-3.6.0.Final.jar", Tried to
find out the reason behind but remain undone.
Now before going into the discussion, I will first try note down the jars that
I have used, as this portion has Given me Immense pain due to
lack of proper Documentation.
jar List
---------------------------------
1) hibernate-core-3.6.0.Final.jar
2) transactions-jta-3.6.4.jar
3) atomikos-util-3.6.4.jar
4) transactions-3.6.4.jar
5) transactions-api-3.6.4.jar
6) transactions-hibernate3-3.6.4.jar
7) transactions-jdbc-3.6.4.jar
8) concurrent-1.3.4.jar
9) cglib-nodep-2.2.3.jar
--------------------------------
Now apart from the above mentioned jars, the jars required to up and run a
Spring application is also required to be taken care of.
Please note: Various custom JTA properties can be set through Atomikos with the help of a property file
known as jta.properties.
But I jave not used it as I have gone with the default properties.
If anybody wishes to use it Proper documentation is alreay there at Atomikos Site.
During Startup an error will crop p saying that the file jta.properties is
not available in the classpath, which can be ignored.
First I will discuss about the configuration part and the issues that I have faced.
Before going into the aforementioned details of the previously mentioned post, lets dive into
the Spring-Data-JPA and Spring-Data-Commons API which I have used for JPA implementation in Spring.
The basic Idea behind Spring-Data-JPA and Spring-Data-Commons implementation, is to keep aside all the boilerplate JPA
implementation code and provide a clean interface to the common DAO methods, in other
word we can say that we can bid goodbye on the DAO layer.
In addition to the common DAO methods which are provided by the API by default custom DATA methods as per
business requirements can be defined very easily without any added overhead, Not only this, another feature of
these api which seems to be very interesting to me is the JPA Criteria API.
The main catch behind this API is the java representation of any type of SQL query (Simple.... Complex.....)
any type. Further the Queries can be made type safe with Java MetaModel classes.
Metamodel classes represents the Domain classes (Entity classes... i.e. classes representing
tables in underlying databases) along with their state and relationship with the other Domain entities.
These metamodel classes can be generated very easily with the help of Ant Task.
All the above mentioned features, Which I have implemented at a very Basic level, with Custom
configuration which can be very helpful in Real Time projects will be Discussed next.
For Furthur Information and all the API related details Spring-Data-JPA and Spring-Data-Commons
documentation should be consulted. They are very much precise,accurate and easy to implement.
So lets, start Now.At the heart of the Spring-Data-JPA lies the Repository implementation,
which contains all the Data Manupulation workarounds.
I have implemented a Generic Repository interface which will be implemented by Domain Specific Repositories,
So that all the Data Access methods lies within the Repository and hence can be accessed from that, including Custom
methods if required.
A bit confusing......... So lets go with the examples to make things a bit Bright.
The Generic Repository used is:
@NoRepositoryBean public interface SpringrestRepository<T, ID extends Serializable> extends JpaRepository<T, ID> { /* * Basic Entity Persistent Specific Methods Declaration */ public void testCustomtoAllRepo(); }See that our Generic Repository extends JpaRepository which contains all generic (By Default)the Data Access and Manipulative methods
(can be verified from the API documentation).
Here T represents the Domain Entity class and
ID represents the Primary Key (Simple or Composite) of the corresponding
Entity class.
The Custom method method for example which I have used here is:testCustomtoAllRepo()
The annotation @NoRepositoryBean has been used here so that no Repository
corresponding to this Bean should be generated by the API as this should be the Base
Repository all our Domain Entity Specific Repository.
This would become more clear as we Progress.
Lets us consider and Domain Entity Car.
@Entity @Table(name="car") public class Car implements Serializable { @SequenceGenerator(name="car_seq", sequenceName="car_seq") @Id @GeneratedValue(strategy = GenerationType.AUTO,generator="car_seq") @Column(name="ID") private Long id; @Column(name="LICENSEPLATE") private String licensePlate; @Column(name="MANUFACTURER") private String manufacturer; @Column(name="MANUFACTUREDATE") private Date manufactureDate; @Column(name="AGE") private int age; @Version private int version; /*@OneToOne @JoinColumn(name="owner_id") private CAR_OWNER carOWNER;*/ public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getLicensePlate() { return licensePlate; } public void setLicensePlate(String licensePlate) { this.licensePlate = licensePlate; } public String getManufacturer() { return manufacturer; } public Date getManufactureDate() { return manufactureDate; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getVersion() { return version; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } public void setManufactureDate(Date manufactureDate) { this.manufactureDate = manufactureDate; } public void setVersion(int version) { this.version = version; } /*public CAR_OWNER getCarOWNER() { return carOWNER; } public void setCarOWNER(CAR_OWNER carOWNER) { this.carOWNER = carOWNER; } */ public String toString() { return "ID:"+id+" licensePlate:"+licensePlate+" manufacturer:"+manufacturer+" manufactureDate"+manufactureDate+" age:"+age+" version:"+version/*+" Car Owner:"+carOWNER*/; } /*public String toString() { return "The car is:"+id+"---> "+licensePlate; }*/ }The Repository corresponding to the Above Domain Entity is:
public interface CarRepository extends SpringrestRepositorySee Our CarRepository extends the base Repository ---- SpringrestRepository{ }
So this is in Short the Repository skeleton Structure, and here is only the interfaces
where lies the implementation?
For Custom configuration we would provide the implementation to the interface
and the have API engine to generate the Implementation Bean object and use this object to
access the repository specific methods.
Again a bit confusing and believe me We will clarify it soon as progress.
The Implementation Bean is:
public class SpringrestRepositoryImpl<T, ID extends Serializable> extends SimpleJpaRepository<T,ID> implements SpringrestRepository<T, ID> { private JpaEntityInformation<T, ?> entityInformation ; private EntityManager em; private SpringRESTPersistenceProvider provider ; private MyLogger myLogger = MyLogFactory.getLogger(this.getClass().getName()); private Class<?> springDataRepositoryInterface; public Class<?> getSpringDataRepositoryInterface() { return springDataRepositoryInterface; } public void setSpringDataRepositoryInterface( Class<?> springDataRepositoryInterface) { this.springDataRepositoryInterface = springDataRepositoryInterface; } public SpringrestRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager,Class<?> repositoryInterface) { super(entityInformation,entityManager); //Assert.notNull(entityInformation); //Assert.notNull(entityManager); this.entityInformation = entityInformation; this.em = entityManager; this.provider = SpringRESTPersistenceProvider.fromEntityManager(entityManager); this.springDataRepositoryInterface = repositoryInterface; myLogger.log(ILoggerLevel.DEBUG, " *** In SpringRESTRepositoryImpl Cons *** repositoryInterface:"+repositoryInterface); } public SpringrestRepositoryImpl(Class<T> domainClass, EntityManager entityManager) { super(domainClass, entityManager); // This is the recommended method for accessing inherited class dependencies. this.em = entityManager; } private Class<T> getDomainClass() { return this.entityInformation.getJavaType(); } @Override public void testCustomtoAllRepo() { // TODO Auto-generated method stub myLogger.log(ILoggerLevel.DEBUG, " *** testCustomtoAllRepo() is on Way *** "); } }As said before SimpleJpaRepository class contains the default Data Access Methods.
So, From the Implementation Class, things are Very little clear now.
Now How the API engine Knows that the Domain Specific Repository interface
would use this Implementation?????
This can be done through custom Factory Bean and Factory classes and these are configured
in Spring-jpa.xml i.e. configuration file.
The Factory Bean class is:
public class SpringrestRepositoryFactoryBeanltT extends JpaRepository<S, ID>, S, ID extends Serializable> extends JpaRepositoryFactoryBean<T, S, ID> { @PersistenceContext private EntityManager entityManager; private MyLogger myLogger = MyLogFactory.getLogger(this.getClass().getName()); @Override public void afterPropertiesSet() /*throws Exception*/ { // TODO Auto-generated method stub myLogger.log(ILoggerLevel.DEBUG, " *** In afterPropertiesSet() of:"+this.getClass().getName()); Assert.notNull(this.entityManager, "EntityManager must not be null!"); super.afterPropertiesSet(); } protected RepositoryFactorySupport doCreateRepositoryFactory() { myLogger.log(ILoggerLevel.DEBUG, " *** In doCreateRepositoryFactory():"+this.getClass().getName()); return createRepositoryFactory(this.entityManager); } protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { myLogger.log(ILoggerLevel.DEBUG, " *** In createRepositoryFactory() :"+this.getClass().getName()); //entityManager = this.entityManager; myLogger.log(ILoggerLevel.DEBUG, "entityManager:"+entityManager); return new SpringrestRepositoryFactory(entityManager); } }And the Factory Bean class is:
public class SpringrestRepositoryFactory<S,ID extends Serializable> extends JpaRepositoryFactory { private EntityManager entityManager; private QueryExtractor extractor; private MyLogger myLogger = MyLogFactory.getLogger(this.getClass().getName()); public SpringrestRepositoryFactory(EntityManager entityManager) { super(entityManager); this.entityManager = entityManager; Assert.notNull(this.entityManager, " Entity Manager in SpringRESTRepositoryFactory must not be NULL "); extractor = SpringRESTPersistenceProvider.fromEntityManager(entityManager); } @Override protected Class<?> getRepositoryBaseClass(RepositoryMetadata repositoryMetadata ) { // TODO Auto-generated method stub myLogger.log(ILoggerLevel.DEBUG, " *** In getRepositoryBaseClass() :"+this.getClass().getName()); getRepositoryMetaDataInfo(repositoryMetadata); return SpringrestRepository.class; } @Override protected Object getTargetRepository(RepositoryMetadata repositoryMetadata) { // TODO Auto-generated method stub myLogger.log(ILoggerLevel.DEBUG, " *** In getTargetRepository() :"+this.getClass().getName()); getRepositoryMetaDataInfo(repositoryMetadata); return getTargetRepository(repositoryMetadata, this.entityManager); } protected <T, ID extends Serializable> JpaRepository<?, ?> getTargetRepository(RepositoryMetadata repositoryMetadata, EntityManager entityManager) { myLogger.log(ILoggerLevel.DEBUG, " *** In getTargetRepository():"+this.getClass().getName()); getRepositoryMetaDataInfo(repositoryMetadata); Class repositoryInterface = repositoryMetadata.getRepositoryInterface(); JpaEntityInformation entityInformation = getEntityInformation(repositoryMetadata.getDomainType()); getEntityInformation(entityInformation); return new SpringrestRepositoryImpl(entityInformation, entityManager,repositoryInterface); } @Override public <T,ID extends Serializable> JpaEntityInformation<T,ID> getEntityInformation(Class<T> domainClass) { myLogger.log(ILoggerLevel.DEBUG, " *** In JpaEntityInformation():"+this.getClass().getName()); return (JpaEntityInformation<T, ID>) JpaEntityInformationSupport.getMetadata(domainClass, this.entityManager); } private void getRepositoryMetaDataInfo(RepositoryMetadata repositoryMetadata) { myLogger.log(ILoggerLevel.DEBUG, repositoryMetadata.getDomainType()+"-->"+repositoryMetadata.getIdType()+" --->"+repositoryMetadata.getRepositoryInterface()); } private void getEntityInformation(JpaEntityInformation entityInformation) { myLogger.log(ILoggerLevel.DEBUG,entityInformation.getClass()+"-->"+entityInformation.getIdType()+"--->"+entityInformation.getJavaType()); } }So the Flow can be described as, The Factory Bean which is being Configured in the .xml file
Generated the Factory and the Factory finally creates an object of the Repository Implmentation Bean.
Any Custom methods if required can be defined here and hence is avilable application wide.
Cool Isn't it.
For Spring Spring JPA we are using the JPA namespace in the configuration file.
The configuration related details are:
<bean id="entityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" abstract="true"> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <!-- property name="showSql" value="true" /> <property name="databasePlatform" value="org.hibernate.dialect.Oracle10gDialect" /--> </bean> </property> <property name="packagesToScan" value="com.springRest.domainEntity"></property> <property name="jpaProperties"> <props> <prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> <prop key="hibernate.max_fetch_depth">3</prop> <prop key="hibernate.jdbc.fetch_size">50</prop> <prop key="hibernate.jdbc.batch_size">10</prop> <prop key="hibernate.show_sql">true</prop> <!-- prop key="hibernate.format_sql">true</prop--> <!-- prop key="hibernate.current_session_context_class">jta</prop--> <prop key="javax.persistence.transactionType">jta</prop> </props> </property> <bean id="emfA" parent="entityManager"> <property name="dataSource" ref="dataSourceBean"></property> </bean> <jpa:repositories base-package="com.springRest.repo.repository" entity-manager-factory-ref="emfA" transaction-manager-ref="transactionManager" factory-class="com.springRest.config.repository.SpringrestRepositoryFactoryBean" > </jpa:repositories> <context:component-scan base-package="com.springRest.service.impl"></context:component-scan>Now, lets describe the JPA namespace Configuration
The base-package should contain all the domain Specific Repository.
entity-manager-factory-ref defines the entity amanger Factory to be used in the
Specific Repository Implementation.
and the factory-class is the Factory Bean implelemntation.
So till now things are little more clear.
Let me get all we have dicussed till Now through an example. which will clarify things more.
Lets us define a Service class containing domain specific Repository (CarRepository) REFERENCE.
The service classes beans are generated through auto detection thorough annotation and with the
help of component-scan base-package element as described in the above configuration,
i.e. all the service classes described in the package define in the component-scan base-package element.
The service class is:
@Service("carService") @Repository @Transactional public class ICarServiceImpl implements ICarService { /* * Here Service Layer is Implemented Through Spring Data Repository Concept.Lets describe the annotations as Bit:
*
* (Normal Entity Manager as fetched from Entity Manager Factory can also be used.)
*
*/ MyLogger logger = MyLogFactory.getLogger(this.getClass().getName()); @Autowired CarRepository carRepository; @Override @Transactional(readOnly=true) public ListfindAll() { // TODO Auto-generated method stub List carList = new ArrayList (); Iterable carIterable = carRepository.findAll(); Iterator carIterator = carIterable.iterator(); while(carIterator.hasNext()) { carList.add(carIterator.next()); } return carList; } @Override @Transactional public Car save(Car car) { logger.log(ILoggerLevel.DEBUG, " *** In save method of Service *** "); Car newCar = null; // TODO Auto-generated method stub try{ logger.log(ILoggerLevel.DEBUG," **** The car Repository is:"+carRepository+" The car is:"+car); newCar =carRepository.save(car); logger.log(ILoggerLevel.DEBUG," **** After Save is called ****"); } catch(Exception e) { logger.log(ILoggerLevel.ERROR,e); e.printStackTrace(); } //return carRepository.save(car); return newCar; } public CarRepository getCarRepository() { return carRepository; } public void setCarRepository(CarRepository carRepository) { this.carRepository = carRepository; } }
@Service: This annotation describes this Bean to be a Service Layer Bean and registers the bean with the name as defined.
@Autowired
CarRepository carRepository: Spring DATA JPA Injects the proper implementation class (as DESCRIBED ABOVE) in the reference,
and with this reference we have preformed various methods, as evident from various methods.
So, till Now what we have dicussed, almost all the things are out of Shadow, regarding various Spring JPA Config and Usage.
So, the DAO layer are no more a requirement now, and we can thus proceed with Spring JPA.
Just Feel free to share any doubts with me, Just Post Your doubts...
I will try to answer ... and till then happy coding and feel the magic of Spring JPA and Spring DATA ;-)
It is really been long since I added up anything and I really apologize for that. Lets continue the above topic and bring it to conclusion.
Next interesting thing that I came across while going through Spring DATA JPA is the criteria API. In a single word it is the java representation of the SQL queries. Every bit of action that can be done through SQL queries is possible through it. This topic is really vast, lets feel some taste of it.
The first and foremost thing in CRITERIA API is the metamodel classes of Domain entity classes, which can be generated through a ANT task.
Say, The Domain entity class for CAR is:
@Entity @Table(name="car") public class Car implements Serializable { @SequenceGenerator(name="car_seq", sequenceName="car_seq") @Id @GeneratedValue(strategy = GenerationType.AUTO,generator="car_seq") @Column(name="ID") private Long id; @Column(name="LICENSEPLATE") private String licensePlate; @Column(name="MANUFACTURER") private String manufacturer; @Column(name="MANUFACTUREDATE") private Date manufactureDate; @Column(name="AGE") private int age; @Version private int version; /*@OneToOne @JoinColumn(name="owner_id") private CAR_OWNER carOWNER;*/ public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getLicensePlate() { return licensePlate; } public void setLicensePlate(String licensePlate) { this.licensePlate = licensePlate; } public String getManufacturer() { return manufacturer; } public Date getManufactureDate() { return manufactureDate; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getVersion() { return version; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } public void setManufactureDate(Date manufactureDate) { this.manufactureDate = manufactureDate; } public void setVersion(int version) { this.version = version; } /*public CAR_OWNER getCarOWNER() { return carOWNER; } public void setCarOWNER(CAR_OWNER carOWNER) { this.carOWNER = carOWNER; } */ public String toString() { return "ID:"+id+" licensePlate:"+licensePlate+" manufacturer:"+manufacturer+" manufactureDate"+manufactureDate+" age:"+age+" version:"+version/*+" Car Owner:"+carOWNER*/; } /*public String toString() { return "The car is:"+id+"---> "+licensePlate; }*/ }It's MetaModel representation is:
@Generated(value = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor") @StaticMetamodel(Car.class) public abstract class Car_ { public static volatile SingularAttributeThe Metamodel class "Car_" is generated through the ANT task:id; public static volatile SingularAttribute manufacturer; public static volatile SingularAttribute age; public static volatile SingularAttribute manufactureDate; public static volatile SingularAttribute licensePlate; public static volatile SingularAttribute version; }
<target name="CREATE-METAMODEL">
<copyfile dest="F:/My_prog/Spring Workspaces/SpringREST/AntLib" src="C:/Users/hcl/Desktop/Spring Related/hibernate-jpamodelgen-1.3.0.Final-dist/hibernate-jpamodelgen-1.3.0.Final/hibernate-jpamodelgen-1.3.0.Final.jar"/>
<javac srcdir="${src}/com/springRest/domainEntity" destdir="${src}/metamodel" failonerror="false" fork="true">
<classpath refid="classpath"/>
<compilerarg value="-proc:only"/>
</javac>
Now using criteria query we are going to query for all cars having owners.
The foreign key in Car_Owner is id of Car.
public String fetchAllCarData() { try{ int i =1; ListIn the above method we are have tried to fetch the car details having car owners.carList = carService.findAll(); for(Car car : carList) { myLogger.log(ILoggerLevel.DEBUG,i+": "+car ); } /* * First we have to create a CriteriaBuilder object, this object * is going to perform all the query building functions. */ CriteriaBuilder cb = em.getCriteriaBuilder(); myLogger.log(ILoggerLevel.DEBUG, " **** Criteria Query using Predicates and Static MetaModel - 123 **** "); /* * From CriteriaBuilder object we are creating an instance of CriteriaQuery with * expected result Type as the Type Parameter. * The expected result type is CarDesc, custom java bean * Any custom java type when expected as a result type of any query * should conform to java beans spefication */ CriteriaQuery criteriaQuery = cb.createQuery(CarDesc.class); /* * Next we are going to create indivudual roots on which * join is to be performed. */ Root car = criteriaQuery.from(Car.class); Root carOwner = criteriaQuery.from(Car_Owner.class); /* * Creating Metamodel instance */ Metamodel metamodel = em.getMetamodel(); /* * Join is being performed and a Predicate object is created */ Predicate predicate1 = cb.equal(car.get(Car_.id), carOwner.get(Car_Owner_.carOwnerPK).get(Car_Owner_PK_.carId)); * * While mapping Query results to Result Domain Objects, * Provide appropiate constructor, for Initialization * criteriaQuery.select(cb.construct(CarDesc.class, car.get("licensePlate"),car.get("manufacturer")));//.where(cb.equal(car.get("id"), carOwner.get("carOwnerPK").get("carId"))); * Predicates ar appended using And, we can use Or or other logical * Operators in case of Multiple Predicates. * * In case of Multiple Predicates all the predicates, that are * to be logically grouped can be kept in a List Structure, * and then AND or OR operators can be applied * criteriaQuery.where(cb.and(predicate1)); /* * Now a TypedQuery instance is being created by executing the CriteriaQuery * object as created in above steps and finally result set is fetched * from TypedQuery instance */ TypedQuery query = em.createQuery(criteriaQuery); List carList = query.getResultList(); for(CarDesc obj:carList) { myLogger.log(ILoggerLevel.DEBUG, " The Data in Domain Form:"+obj); } return "JPASuccess"; } catch(Exception e) { myLogger.log(ILoggerLevel.ERROR, e); return null; } }
The car details are encapsulated in custom java bean "CarDesc".
This is in very short a glimpse of the Criteria API, please go through its documentation , It's really nice and interesting.
Comments
Post a Comment