I'm trying to learn hibernate and spring. The first thing I want to do is get some data from database using Hibernate.
What I am trying to do is getting all data from data base but I get null pointer exception.
Here is my code;
City.java (under com.hopyar.dao package)
#Entity
#Table(name = "Cities")
public class City implements Serializable{
private static final long serialVersionUID = 2637311781100429929L;
#Id
#GeneratedValue
#Column(name = "c_id")
int id;
#Column(name = "c_name")
String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
CityService.java (under com.hopyar.service package)
#Service
public class CityService {
#PersistenceContext
private EntityManager em;
#Transactional
public List<City> getAllCities(){
List<City> result = em.createQuery("Select c From Cities c", City.class)
.getResultList(); // This is where I get the exeption.
System.out.println();
return result;
}
}
spring-context.xml(under webapp/WEB-INF)
<?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<!-- Enable annotation-based Spring MVC controllers (eg: #Controller annotation) -->
<mvc:annotation-driven/>
<!-- Classpath scanning of #Component, #Service, etc annotated class -->
<context:component-scan base-package="com.hopyar" />
<!-- Resolve view name into jsp file located on /WEB-INF -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- MySQL Datasource with Commons DBCP connection pooling -->
<bean class="org.apache.commons.dbcp.BasicDataSource" id="dataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/myproject"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</bean>
<!-- EntityManagerFactory -->
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- Transaction Manager -->
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<!-- Enable #Transactional annotation -->
<tx:annotation-driven/>
</beans>
Main.java(under com.hopyar.test package)
public class Main {
public static void main(String[] args) {
CityService service = new CityService();
List<City> cities = service.getAllCities();
System.out.println(cities.size());
}
}
You are instantiating service as new CityService(), which is wrong because you are bypassing Spring. This means your annotations are not proccessed, and em is null. You need to get your service from spring context.
CityService service = applicationContext.getBean("cityService");
You can try to use autowired annotation on CityService, and Spring will instantiate it.
Related
I am not able to auto-create table from maven spring mvc.
I was doing a spring mvc project using maven. By far i have got no errors but when i am trying to create table in my database using applicationconfig.xml it is not working. i have searched over the internet but my applicationconfig.xml seems fine to me. I have got no errors. Still the table is not created..
applicationconfig.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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<bean id="entityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="com.milan.entities" /><!--scans model/entity/domain(name 3 but same) and registers-->
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create-drop</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/inventorymanagement" />
<property name="username" value="root" />
<property name="password" value="" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManager" />
</bean>
<tx:annotation-driven />
<bean id="persistenceExceptionTranslationPostProcessor"
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
</beans>
User Class
package com.milan.entities;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
public class User implements Serializable{
#Id
#Column(name = "USER_ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long userId;
#Column(name = "USERNAME")
private String userName;
#Column(name = "PASSWORD")
private String password;
#Column(name = "IS_ENABLEd")
private boolean isEnabled;
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isIsEnabled() {
return isEnabled;
}
public void setIsEnabled(boolean isEnabled) {
this.isEnabled = isEnabled;
}
}
There is no error while running the program however the table is not created automatically.
Put #Entity on your User class, if the table still not created try putting below annotations on the class:
#Entity
#Table(name = "`user`")
Could be happening because User is a reserve word in DB.
I have an issue with my project using Spring (4.2.4 Release) and JPA (2.1)
To be brief the problem is in the part of code in file "Book.java":
#Table(name = "book")
#NamedQueries({
#NamedQuery(name = "Book.getBooks", query="select b from com.jpaProSpring.Book b ")
})
#Entity(name = "Book")
public class Book implements Serializable {
private int id;
private String title;
private String description;
public Book() {
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "id")
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
#Column
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
#Column
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
}
and particulary in
query = "select b from com.jpaProSpring.Book b" )
My IntelliJ highlights the Book and says that class is not en entity. And I have no idea, why it is so given that I was doing an example from the book.
Link to my project https://github.com/yuraguz/LearnORM.git
My spring-config.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:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3310/testdb"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
<property name="initialSize" value="5"/>
<property name="maxActive" value="10"/>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<bean id="emf"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="packagesToScan" value="com.jpaProSpring" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</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>
</props>
</property>
</bean>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<context:annotation-config />
<context:component-scan base-package="com.jpaProSpring" />
</beans>
P.S: I know entities must be declared in persistence.xml in META-INF/ source. But if I understand correctly Spring4 make it possible to config project without persistance.xml. So, I don't use it.
If you use InellyJ Idea, possible you didn't add JPA facet in your project. Try open menu "File"->"Project Structure", then select in list of Project Settings section named "Facets". Check if you have configured JPA facet in list of facets. If you don't see JPA facet, just add it (by pressing "+" button). Optionally, you can specify persistence.xml (if you have it) and Default JPA provider. Hope this will help.
Consider this example in which I have created two JPA entities and used Spring Data JPA repositories to perform simple CRUD -
import java.sql.Timestamp;
import javax.persistence.Version;
#MappedSuperclass
public class AbstractValueObject {
#Id
#GeneratedValue
private Long id;
#Version
#Column(name = "time_stamp")
private Timestamp version;
public Long getId() {
return id;
}
#Override
public String toString() {
if (id == null) {
return "";
}
return id.toString();
}
}
#Entity
#Table(name = "demo")
public class Demo extends AbstractValueObject {
private String name;
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "demo")
private List<Owner> owners;
public Demo() {
owners = new ArrayList<>();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Owner> getOwners() {
return Collections.unmodifiableList(owners);
}
public void addOwner(Owner owner) {
this.owners.add(owner);
owner.setDemo(this);
}
public void addAllOwners(List<Owner> owners) {
this.owners.addAll(owners);
for (Owner owner : owners) {
owner.setDemo(this);
}
}
public void update(Demo demo) {
this.setName(demo.getName());
this.owners.clear();
this.addAllOwners(demo.getOwners());
}
}
#Entity
#Table(name = "owner")
public class Owner extends AbstractValueObject {
private String attribute;
#ManyToOne(cascade = CascadeType.ALL, optional = false)
#JoinColumn(name = "demo_id", nullable = false)
private Demo demo;
public String getAttribute() {
return attribute;
}
public void setAttribute(String attribute) {
this.attribute = attribute;
}
public Demo getDemo() {
return demo;
}
public void setDemo(Demo demo) {
this.demo = demo;
}
}
After that, I have created a JPA repository for the Demo entity, extending from JpaRepository -
import org.springframework.data.jpa.repository.JpaRepository;
public interface DemoRepository extends JpaRepository<Demo, Long> {}
Corresponding service implementation -
import javax.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
public class DemoServiceImpl implements DemoService {
#Resource
private DemoRepository demoRepository;
#Override
#Transactional
public Demo create(Demo demo) {
return demoRepository.save(demo);
}
#Override
#Transactional
public Demo update(long id, Demo demo) {
Demo dbDemo = demoRepository.findOne(id);
if (dbDemo == null) {
return demo;
}
dbDemo.update(demo);
return dbDemo;
}
#Transactional
public void testRun() {
Owner owner = new Owner();
owner.setAttribute("attribute");
Demo demo = new Demo();
demo.setName("demo");
demo.addOwner(owner);
this.create(demo);
demo.setName("another");
this.update(demo.getId(), demo);
}
}
persistence.xml file -
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="jpa-optimistic-locking" transaction-type="RESOURCE_LOCAL">
</persistence-unit>
</persistence>
Spring app-context.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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="com.keertimaan.example.jpaoptimisticlocking" />
<jpa:repositories base-package="com.keertimaan.example.jpaoptimisticlocking.repository" />
<bean id="demoService" class="com.keertimaan.example.jpaoptimisticlocking.service.DemoServiceImpl" />
<!-- JPA/Database/Transaction Configuration -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test" />
<property name="user" value="root" />
<property name="password" value="admin123" />
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="2" />
<property name="acquireIncrement" value="1" />
<property name="maxStatements" value="5" />
<property name="idleConnectionTestPeriod" value="500" />
<property name="maxIdleTime" value="1000" />
<property name="loginTimeout" value="800" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="jpa-optimistic-locking" />
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="persistenceProvider">
<bean class="org.hibernate.jpa.HibernatePersistenceProvider" />
</property>
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">validate</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
</beans>
Now whenever I try to update an entity like this on Windows 7 -
public class App {
public static void main(String[] args) {
DemoService demoService = (DemoService) SpringHelper.INSTANCE.getBean("demoService");
demoService.testRun();
}
}
I get an exception like this -
Exception in thread "main"
org.springframework.orm.ObjectOptimisticLockingFailureException:
Object of class
[com.keertimaan.example.jpaoptimisticlocking.domain.Demo] with
identifier [4]: optimistic locking failed; nested exception is
org.hibernate.StaleObjectStateException: Row was updated or deleted by
another transaction (or unsaved-value mapping was incorrect) :
[com.keertimaan.example.jpaoptimisticlocking.domain.Demo#4] at
org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:228)
at
org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:155)
at
org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:519)
at
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
at
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
at
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
at
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
at
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy31.testRun(Unknown Source) at
com.keertimaan.example.jpaoptimisticlocking.App.main(App.java:9)
Caused by: org.hibernate.StaleObjectStateException: Row was updated or
deleted by another transaction (or unsaved-value mapping was
incorrect) :
[com.keertimaan.example.jpaoptimisticlocking.domain.Demo#4] at
org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2541)
at
org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3285)
at
org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3183)
at
org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3525)
at
org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:159)
at
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:463)
at
org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:349)
at
org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350)
at
org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1222)
at
org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:425)
at
org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at
org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:177)
at
org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:77)
at
org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515)
... 9 more
If I run the same example in Ubuntu, then I get no exception at all and my application completes successfully. Why is that?
I am using Windowsw 7 64-bit edition -
OS Name: Microsoft Windows 7 Enterprise
OS Version: 6.1.7601 Service Pack 1 Build 7601
and my Ubuntu version is 12.04.5 64-bit edition.
JDK used in Windows: jdk7 update 75
JDK used in Ubuntu: jdk7 update 51
MySQL Server version in Windows: 5.6.23-log MySQL Community Server (GPL)
MySQL Server version in Ubuntu: 5.5.41-0ubuntu0.12.04.1 (Ubuntu)
I have a feeling that this is related to the timestamp precision of MySQL 5.6. MySQL 5.6.4 introduced microsecond precision, which will cause a version mismatch, and the locking will fail.
This is not related to your problem directly but in a highly concurrent environment you should not use timestamp as your version as two entity might have the same time! It's better to use a long/int version like below-
#Version
long version;
Also from design perspective please make your super class abstract as well. Can you check if changing these solves your problem?
Here is my jpaContext.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:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:annotation-config />
<context:component-scan base-package="com.pluralsight"/>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor">
</bean>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="punit"></property>
<property name="dataSource" ref="dataSource"></property>
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"></property>
</bean>
</property>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.dialect"
value="org.hibernate.dialect.MySQL5InnoDBDialect">
</entry>
<entry key="hibernate.hbm2ddl.auto" value="none"></entry>
<entry key="hibernate.format_sql" value="true"></entry>
</map>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory"
ref="entityManagerFactory">
</property>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="com.microsoft.sqlserver.jdbc.SQLServerDriver">
</property>
<property name="url"
value="jdbc:sqlserver://123.123.123.123:1433;databaseName=WikiGenome">
</property>
<property name="username" value="xxx"></property>
<property name="password" value="xxx"></property>
</bean>
</beans>
Here is my Disease.java:
#Entity
#Table(name="Disease")
public class Disease {
#Id
#GeneratedValue
#Column(name="DiseaseID")
public int DiseaseID;
#Column(name="Name")
public String Name;
}
Here is my another class:
#Entity
#Table(name="ChrPosDisease")
public class ChrPosDisease implements Serializable{
#Id
#Column(name="chr")
public String chr;
#Id
#Column(name="pos")
public int pos;
#Id
#Column(name="DiseaseID")
public int diseaseID;
}
I am new to hibernate and spring mvc framework and I just follows the guide in the tutorials.
I can query the result by using:
#SuppressWarnings({ "unchecked"})
public List getDiseaseByName(String name) {
Query query = em.createQuery("Select d From Disease d Where d.Name=?1").setParameter(1,name);
List diseaseList=query.getResultList();
return diseaseList;
}
However, when I join two table by DiseaseID, it gives following error.
java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [Select d From cuhk.cse.fyp.model.Disease d JOIN ChrPosDisease c Where d.DiseaseID=c.DiseaseID AND d.Name=?1]
I don't got the error when querying the result with one table only.
Here is the code that I used to join that two table:
#SuppressWarnings({ "unchecked"})
public List getJoinDiseaseByName(String name) {
Query query = em.createQuery("Select d From Disease d JOIN ChrPosDisease c Where d.DiseaseID=c.DiseaseID AND d.Name=?1").setParameter(1,name);
List diseaseList=query.getResultList();
return diseaseList;
}
What's wrong?
Thanks for help.
Supplementary:
Updated ChrPosDisease
#SuppressWarnings("serial")
#Entity
#Table(name="ChrPosDisease")
public class ChrPosDisease implements Serializable{
#Id
#Column(name="chr")
public String chr;
#Id
#Column(name="pos")
public int pos;
#Column(name="DiseaseID")
public int diseaseID;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="DiseaseID",nullable=false)
private Disease disease;
}
Updated Disease:
#SuppressWarnings("serial")
#Entity
#Table(name="Disease")
public class Disease implements Serializable{
#Id
#GeneratedValue
#Column(name="DiseaseID")
public int DiseaseID;
#Column(name="Name")
public String Name;
#OneToMany(fetch = FetchType.LAZY, mappedBy = "ChrPosDisease")
private Set<ChrPosDisease> chrPosDisease = new HashSet<ChrPosDisease>();
}
I used above entity and there is exception in deploying.
Do I need to add anything else?
I think you should not use d.ChrPosDisease instead use just ChrPosDisease as d is an alias for only Disease entity.
and it should work.
let me know if it doesn't work.
You should have mapping entry as:
#OneToMany(fetch = FetchType.LAZY, mappedBy = "disease")
private Set<ChrPosDisease> chrPosDisease = new HashSet<ChrPosDisease>();
mappedBy attribute notifies that the field is mapped by that particular entity property. So, this property should be the one on which connects entity on ManyToOne side.
Here Disease has many ChrPosDisease. And ChrPosDisease has one Disease. So mapped by column should be the one by which OneToMany field is bound with property on ManyToOne side.
I have used Java EE 6 before and I have created a connection resource (pooled) on the server and then bound it to a JNDI name which I have referenced inside the jta-data-source element tag in the Persistence.xml file.
Now I use Spring 3 and I have a hard time understanding all the different beans that I need to set up and why need to do so. EJB 3 automatically wrap the methods in transactions. In Spring it seems like you need to configure a transaction manager, however I don't know. Need explanation.
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/myapp" expected-type="javax.sql.DataSource"/>
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
</property>
<property name="packagesToScan" value="com.myapp.app"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.PostgreSQL82Dialect
</prop>
</props>
</property>
</bean>
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
I understand the jndi lookup for the data source, however I don't understand the rest thourougly. I am not able to insert/persist objects with this configuration.
I need an explanation on how Spring 3 differs from Java EE 6 in this area, and how to do it the same way.
After thinking a little more on your original question, I'd like to add:
Spring doesn't automatically wrap every method with a Transaction. You have to tell Spring where you want your Transactional Boundaries to be. You do that with either XML config or by using the #Transactional annotation.
You should have a look at where you should declare transactions - here and here.
You should have a look at Spring's Transaction Management - here.
You should have a look at Transaction Config - here.
I am still of the opinion that your config is good and that the trouble you are having lies within the beans attempting to use your EntityManager. I renew my request for you to post that, as I'm certain I could get you going if I could see it.
I've looked at your configuration and I can't find anything wrong with it. As an example, I will provide (at the bottom) something I have in a working application right now.
I don't believe your problem is within your configuration, but in your usage of the configured beans. If you could provide code showing me (us) how you are interacting with your EntityManager, I could probably identify your issue(s).
I'll provide you with working examples of a Entity, Repository, and XML Config to try and help you locate your issue:
Spring Config (applicationContext.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:p="http://www.springframework.org/schema/p"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<context:annotation-config />
<context:component-scan base-package="com.company.app.dao" />
<context:component-scan base-package="com.company.app.service" />
<jee:jndi-lookup id="dataSource"
jndi-name="jdbc/Test" />
<bean id="jpaDialect"
class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
<bean id="jpaAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
<bean id="entityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter" ref="jpaAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
<property name="packagesToScan" value="com.company.app.model" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManager" />
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
</beans>
Model
import org.hibernate.validator.constraints.Length;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
#Entity
public class User {
#Id
private String id = UUID.randomUUID().toString();
#Column
#Length(min = 3, max = 25)
private String name;
#OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER, orphanRemoval = true)
#JoinColumn(name = "userId", nullable = false)
private Set<Contact> contacts = new HashSet<Contact>();
public UUID getId() {
return UUID.fromString(id);
}
public void setId(UUID id) {
this.id = id.toString();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Contact> getContacts() {
return contacts;
}
public void setContacts(Set<Contact> contacts) {
this.contacts = contacts;
}
public void addContact(Contact contact) {
this.contacts.add(contact);
}
public void removeContact(Contact contact) {
this.contacts.remove(contact);
}
}
Repository
import com.company.app.model.User;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaQuery;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
#Repository
public class UserDao {
#PersistenceContext
private EntityManager em;
#Transactional(propagation = Propagation.REQUIRED)
public void createUser(User user) {
em.persist(user);
}
#Transactional(propagation = Propagation.REQUIRED, readOnly = true)
public User readUserById(UUID id) {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
query.where (em.getCriteriaBuilder().equal(query.from(User.class).get("id"),id.toString()));
return em.createQuery(query).getSingleResult();
}
#Transactional(propagation = Propagation.REQUIRED, readOnly = true)
public Set<User> readAll() {
CriteriaQuery<User> query = em.getCriteriaBuilder().createQuery(User.class);
query.from(User.class);
return new HashSet<User>(em.createQuery(query).getResultList());
}
#Transactional(propagation = Propagation.REQUIRED)
public User update(User user) {
return em.merge(user);
}
#Transactional(propagation = Propagation.REQUIRED)
public void delete(User user) {
em.remove(user);
}
}