org.hibernate.exception.GenericJDBCException: ERROR: cross-database references are not implemented - spring

1) Dispatcher-Servlet
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driverClassName}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${dialect}</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.default_catalog.null"></prop>
</props>
</property>
</bean>
2) database.properties
driverClassName=org.postgresql.Driver
dialect=org.hibernate.dialect.PostgreSQLDialect
url=jdbc:postgresql://192.168.1.20:5432/GSW
username=postgres
password=postgres
3) Java Class
#Entity
#Table(name = "std_users_v", catalog = "GSW", schema = "public")
#NamedQueries({
#NamedQuery(name = "StdUsersV.findAll", query = "SELECT s FROM StdUsersV s")})
public class StdUsersV implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#Column(name = "id")
private Integer id;
#Column(name = "user_group_id")
private BigInteger userGroupId;
#Size(max = 50)
#Column(name = "user_name", length = 50)
private String userName;
#Size(max = 100)
#Column(name = "password", length = 100)
private String password;
#Column(name = "org_unit_id")
private BigInteger orgUnitId;
#Column(name = "active_flag")
private Boolean activeFlag;
#Column(name = "start_date")
#Temporal(TemporalType.TIMESTAMP)
private Date startDate;
#Column(name = "end_date")
#Temporal(TemporalType.TIMESTAMP)
private Date endDate;
#Column(name = "created_by")
private BigInteger createdBy;
#Column(name = "creation_date")
#Temporal(TemporalType.TIMESTAMP)
private Date creationDate;
#Column(name = "updated_by")
private BigInteger updatedBy;
#Column(name = "update_date")
#Temporal(TemporalType.TIMESTAMP)
private Date updateDate;
#Size(max = 20)
#Column(name = "user_group_name", length = 20)
private String userGroupName;
getters and setters...
I am using Postgresql. While i am trying to fetch data from Table StdUserV.java i am getting the following error-
org.hibernate.exception.GenericJDBCException: ERROR: cross-database references are not implemented: "gsw.public.std_users_v"
I have googled around and found the solution that i need to remove bolded text from gsw.public.std_users_v (i.e. catalog) but i am not getting how can i do it. The property "hibernate.default_catalog.null" was one effort towards this issue. I welcome the other solutions too for this "cross-reference" problem.
Please help.

found solution after changing-
#Table(name = "std_users_v", catalog = "GSW", schema = "public")
to-
#Table(name = "std_users_v")

I had the same problem with Spring Boot using Postgres. I figured out that you only have to remove the Table.catalog attribute. In case you have multiple schemas in your Postgres database then I advise you to leave the schema attribute.
This results in the query using the schema as a prefix like:
Hibernate: select count(*) as col_0_0_ from public.std_users_v
If you don't remove the catalog attribute it ends up in:
Hibernate: select count(*) as col_0_0_ from GSW.public.std_users_v
ERROR: cross-database references are not implemented: "GSW.public.std_users_v"

Related

Spring could not prepare statement because of a not found column

I'm working with jhipster, I got the following jdl format:
I've made some modification on the domains that looks like:
#Entity
#Table(name = "client_account")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class ClientAccount implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private Long id;
#NotNull
#Column(name = "first_name", nullable = false)
private String firstName;
#NotNull
#Column(name = "last_name", nullable = false)
private String lastName;
#NotNull
#Column(name = "phone", nullable = false)
private String phone;
#Column(name = "identity")
private String identity;
#Column(name = "referal")
private String referal;
#Column(name = "refered_by")
private String referedBy;
#OneToOne
#MapsId
private User user;
#OneToMany(mappedBy = "clientAccount")
private Set<Reputation> reputations = new HashSet<>();
#OneToMany(mappedBy = "clientAccount")
private Set<Trip> trips = new HashSet<>();
and the reputations domain:
#Entity
#Table(name = "reputation")
public class Reputation implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Column(name = "rate", nullable = false)
private Integer rate;
#Column(name = "comment")
private String comment;
#ManyToOne
#JsonIgnoreProperties("reputations")
private TransporterAccount transporterAccount;
#ManyToOne
#JsonIgnoreProperties("reputations")
private ClientAccount clientAccount;
The user domain:
#Entity
#Table(name = "jhi_user")
public class User extends AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#NotNull
#Pattern(regexp = Constants.LOGIN_REGEX)
#Size(min = 1, max = 50)
#Column(length = 50, unique = true, nullable = false)
private String login;
#JsonIgnore
#NotNull
#Size(min = 60, max = 60)
#Column(name = "password_hash", length = 60, nullable = false)
private String password;
#Size(max = 50)
#Column(name = "first_name", length = 50)
private String firstName;
#Size(max = 50)
#Column(name = "last_name", length = 50)
private String lastName;
#Email
#Size(min = 5, max = 254)
#Column(length = 254, unique = true)
private String email;
#NotNull
#Column(nullable = false)
private boolean activated = false;
#Size(min = 2, max = 10)
#Column(name = "lang_key", length = 10)
private String langKey;
#Size(max = 256)
#Column(name = "image_url", length = 256)
private String imageUrl;
#Size(max = 20)
#Column(name = "activation_key", length = 20)
#JsonIgnore
private String activationKey;
#Size(max = 20)
#Column(name = "reset_key", length = 20)
#JsonIgnore
private String resetKey;
#Column(name = "reset_date")
private Instant resetDate = null;
#JsonIgnore
#ManyToMany
#JoinTable(
name = "jhi_user_authority",
joinColumns = {#JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {#JoinColumn(name = "authority_name", referencedColumnName = "name")})
#BatchSize(size = 20)
private Set<Authority> authorities = new HashSet<>();
The Transporter liquibase is mapped as follow:
<changeSet id="20200218210800-1" author="jhipster">
<createTable tableName="client_account">
<column name="user_id" type="bigint">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="first_name" type="varchar(255)">
<constraints nullable="false" />
</column>
<column name="last_name" type="varchar(255)">
<constraints nullable="false" />
</column>
<column name="phone" type="varchar(255)">
<constraints nullable="false" />
</column>
<column name="identity" type="varchar(255)">
<constraints nullable="true" />
</column>
<column name="referal" type="varchar(255)">
<constraints nullable="true" />
</column>
<column name="refered_by" type="varchar(255)">
<constraints nullable="true" />
</column>
<!-- jhipster-needle-liquibase-add-column - JHipster will add columns here, do not remove-->
</createTable>
</changeSet>
<changeSet id="20200218210800-2" author="jhipster">
<addForeignKeyConstraint baseColumnNames="user_id"
baseTableName="client_account"
constraintName="fk_client_account_user_id"
referencedColumnNames="id"
referencedTableName="jhi_user"/>
</changeSet>
and the reputations liquibase:
<changeSet id="20200218210700-1-data" author="jhipster" context="faker">
<loadData
file="config/liquibase/fake-data/reputation.csv"
separator=";"
tableName="reputation">
<column name="id" type="numeric"/>
<column name="rate" type="numeric"/>
<column name="comment" type="string"/>
<!-- jhipster-needle-liquibase-add-loadcolumn - JHipster (and/or extensions) can add load columns here, do not remove-->
</loadData>
</changeSet>
<changeSet id="20200218210700-2" author="jhipster">
<addForeignKeyConstraint baseColumnNames="transporter_account_id"
baseTableName="reputation"
constraintName="fk_reputation_transporter_account_id"
referencedColumnNames="user_id"
referencedTableName="transporter_account"/>
<addForeignKeyConstraint baseColumnNames="client_account_id"
baseTableName="reputation"
constraintName="fk_reputation_client_account_id"
referencedColumnNames="user_id"
referencedTableName="client_account"/>
</changeSet>
Still I'm getting the following stacktrace error:
select reputation0_.id as id1_14_, reputation0_.client_account_user_id
as client_a4_14_, reputation0_.comment as comment2_14_,
reputation0_.rate as rate3_14_,
reputation0_.transporter_account_user_id as transpor5_14_ from
reputation reputation0_ order by reputation0_.id asc limit ?
[42122-200] 2020-02-20 09:48:03.515 ERROR 23616 --- [ XNIO-1 task-7]
c.a.dropme.aop.logging.LoggingAspect : Exception in
com.abdrid.dropme.service.ReputationQueryService.findByCriteria() with
cause = 'org.hibernate.exception.SQLGrammarException: could not
prepare statement' and exception = 'could not prepare statement; SQL
[select reputation0_.id as id1_14_,
reputation0_.client_account_user_id as client_a4_14_,
reputation0_.comment as comment2_14_, reputation0_.rate as rate3_14_,
reputation0_.transporter_account_user_id as transpor5_14_ from
reputation reputation0_ order by reputation0_.id asc limit ?]; nested
exception is org.hibernate.exception.SQLGrammarException: could not
prepare statement'
I got a similar issue ... I added a new Field in an Entity known as title (String) and jhipster entity sub-generator worked well enough ... got no issues
code got compiled and portal was also working - but when I tried listing the entity page - the ajax call gave 500 Http Status - with internal server as "prepared statement could not be created" ...
I did
./mvnw clean integration-test
and then ran the ./mvnw normally again. All the cached code was flushed and portal started working back.
The table name you used, User, is a reserved keyword for H2 databases ?
First try to surround table name of User with double quotes. If it does not work, rename your table with a name like Employee.
There is a list of keywords that can't be used as identifiers (table names, column names and so on), unless they are quoted (surrounded with double quotes).
http://www.h2database.com/html/advanced.html#keywords

Spring data jpa save does not work. What am I missing?

I have an entity BaseEntity, an entity Account, an AccountRepository, a bean calling the save-method of the repository and an arquillian-test.
Running the test does not work and I do not know why. Maybe someone can tell me what I am missing.
#EqualsAndHashCode(of = "id")
#MappedSuperclass
#Getter
#Setter
public abstract class BaseEntity implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Temporal(TemporalType.TIMESTAMP)
private Date created;
#Temporal(TemporalType.TIMESTAMP)
private Date updated;
private String entityname;
public BaseEntity() {
this.created = new Date();
this.updated = this.created;
this.entityname = UUID.randomUUID().toString();
}
#PreUpdate
#PrePersist
public void update() {
this.updated = new Date();
}
}
#Entity
#Getter
#Setter
#ToString
#Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Account extends BaseEntity {
#Embedded
#Valid
#NotNull
private Address address;
#Column(length = 20)
#Size(min = 6, max = 20)
#NotNull
private String telephone;
#Column(unique = true, nullable = false)
#Email
#NotNull
private String email;
#Column(length = 40)
#NotNull
private String passhash;
#Column(length = 5)
#NotNull
private Language preferredLanguage;
#Column(length = 32)
private String passwordResetKey;
#Column(length = 32)
private String emailConfirmationKey;
#NotNull
private AccountStatus status;
#Transactional
#Repository
public interface AccountRepository extends JpaRepository<Account, Long>,
CrudRepository<Account, Long> {
Account findByEmail(String email);
}
#Transactional
public class RegistrationBean {
#Inject
private AccountRepository accountRepository;
public Account register(Account _account) {
System.out.println("Id before saving: " + _account.getId());
Account account = this.accountRepository.save(_account);
System.out.println("Id after saving: " + account.getId());
System.out.println("How many accounts are there after saving? : " +
this.accountRepository.count());
return account;
}
#RunWith(Arquillian.class)
public class RegistrationTest {
#Deployment
public static WebArchive createDeployment() {
WebArchive archive = ShrinkWrap.create(WebArchive.class)
.addPackages(true, "net.company")
.addAsResource("META-INF/beans.xml", "WEB-INF/beans.xml")
.addAsResource("persistence-test.xml", "META-INF/persistence.xml");
System.out.println(archive.toString(true));
return archive;
}
#Inject
private RegistrationBean registrationBean;
#Test
public void testRegisterAndLoadPerson() {
Person person = giveMeAValidPerson();
System.out.println("************ 1 Person: " + person.toString());
person = (Person) this.registrationBean.register(person);
System.out.println("************ 2 Person: " + person.toString());
Account loadedPerson =
(this.registrationBean.getAccountByEmail(person.getEmail()));
System.out.println("*************loadedPerson: " + loadedPerson.toString());
}
}
Under META-INF I have application.properties, beans.xml and persistence.xml
application.properties:
#Database Configuration
db.driver=com.mysql.jdbc.Driver
db.url=jdbc:mysql://localhost/testApp
db.username=testApp
db.password=testApp
beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
<jpa:repositories base-package="net.company.app.repositories" />
<context:property-placeholder location="classpath:application.properties"
ignore-resource-not-found="false"/>
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource">
<property name="driverClass" value="${db.driver}"/>
<property name="jdbcUrl" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
</bean>
</beans:beans>
persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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">
<persistence-unit name="net.company_OurAppPU" transaction-type="RESOURCE_LOCAL">
<class>net.wakeit.agency.entities.Account</class>
<class>net.wakeit.agency.entities.Person</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost
/testAgency"/>
<property name="javax.persistence.jdbc.user" value="testApp"/>
<property name="javax.persistence.jdbc.password" value="testApp"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.archive.autodetection" value="class"/>
<property name="hibernate.transaction.manager_lookup_class"
value="org.hibernate.transaction.SunONETransactionManagerLookup"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>
</properties>
</persistence-unit>
</persistence>
The Id always stays null and findAll does not give any Accounts after saving. :-
I do not see, what I am missing.
Help is highly appreciated!

Error in entity retrieval

I am attempting to handle an 'entity' through annotation instead of a hibernate xml mapping.
I face a situation where addition succeeds but retrieval fails - help is appreciated.
Model class:
#Entity
#Table(name = "PERSON")
public class Person implements Serializable {
private static final long serialVersionUID = -5527566248002296042L;
#Id
#Column(name = "ID")
#GeneratedValue
private Integer id;
#Column(name = "FIRST_NAME")
private String firstName;
#Column(name = "LAST_NAME")
private String lastName;
#Column(name = "MONEY")
private Double money;
.....setters and getters
}
spring configuration:
<context:annotation-config />
<context:component-scan base-package="org.spring.entity,org.spring.service" />
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
....
</bean>
<!-- Hibernate session factory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
...
<property name="packagesToScan">
<list>
<value>org.spring.entity</value>
<value>org.spring.service</value>
</list>
</property>
<property name="hibernateProperties">
...
</property>
</bean>
Service class:
public void add(String firstName, String lastName, Double money) {
// Retrieve session from Hibernate
Session session = sessionFactory.openSession();
try{
// Create a new person
Person person = new Person();
person.setFirstName(firstName);
person.setLastName(lastName);
person.setMoney(money);
// Save
session.save(person);
}
finally{
session.close();
}
}
public void edit(Integer id, String firstName, String lastName, Double money) {
// Retrieve session from Hibernate
Session session = sessionFactory.openSession();
try{
// Retrieve existing person via id
Query query = session.createQuery("FROM Person WHERE ID=?");<=FAILS HERE
query.setInteger(0, id);
Person person = (Person)query.list().get(0);
......
}
The error is as below:
Exception in thread "main" org.hibernate.hql.internal.ast.QuerySyntaxException:
person is not mapped [from person where ID=?]
at org.hibernate.hql.internal.ast.util.SessionFactoryHelper.requireClass
Persister(SessionFactoryHelper.java:180)
at org.hibernate.hql.internal.ast.tree.FromElementFactory.addFromElement
(FromElementFactory.java:110)
at org.hibernate.hql.internal.ast.tree.FromClause.addFromElement(FromCla
use.java:93)
at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromElement(HqlSqlW
alker.java:324)
Your HQL is wrong, Do this way:
(in case of multiple results, their might be some syntax left right, please check.)
Query query = session.createQuery("FROM Person WHERE ID=:ID")
List list=query.setParameter("ID",ID).list();
or
(in case of Single result)
Person person =new Person ();
person =(Person ) session.get(Person .class, ID);

Spring Hibernate JPA not persisting cloud foundry

I'm working on a project using spring hibernate & jpa and I'm deploying it on cloud foundry. My problem is that when I call the Dao to persist my entity to the mysql database nothing happens. No errors are thrown, I've tried wrapping the persist in a try catch block and nothing.
I have the show sql property in persistance.xml set to true. When I other Dao methods that just query the database I can see the SQL that gets run. But when I try the persist no SQL gets wrote to the console.
Sample console feedback from a query
Hibernate: select animal0_.animal_id as animal1_1_, animal0_.about as about1_, animal0_.animaltype as animaltype1_, animal0_.breed as breed1_, animal0_.date_in as date5_1_, animal0_.date_out as date6_1_, animal0_.image_1 as image7_1_, animal0_.image_1_content_type as image8_1_, animal0_.image_1_file_name as image9_1_, animal0_.image_1_file_size as image10_1_, animal0_.image_2 as image11_1_, animal0_.image_2_content_type as image12_1_, animal0_.image_2_file_name as image13_1_, animal0_.image_2_file_size as image14_1_, animal0_.image_3 as image15_1_, animal0_.image_3_content_type as image16_1_, animal0_.image_3_file_name as image17_1_, animal0_.image_3_file_size as image18_1_, animal0_.name as name1_, animal0_.status as status1_ from animals animal0_
INFO : com.lasthope.web.animals.service.AnimalsServiceImpl - Found 0 animals in care.
Sample console feedback from the persist:
INFO : com.lasthope.web.animals.service.AnimalsServiceImpl - Saving Gerry to database.
INFO : com.lasthope.web.animals.dao.AnimalsDaoImpl - DAO, saving animal Gerry ID: null
Any feedback would be greatly appreciated!
root-context.xml:
<cloud:data-source id="dataSource" />
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
</bean>
Service:
#Service("animalsService")
public class AnimalsServiceImpl implements AnimalsService {
#Autowired
private AnimalsDao animalsDao;
#Override
#Transactional
public void saveAnimal(Animal animal) {
logger.info("Saving "+animal.getName()+ " to database.");
animalsDao.saveAnimal(animal);
}
DAO:
#Repository("animalsDao")
public class AnimalsDaoImpl implements AnimalsDao {
private static final Logger logger = LoggerFactory.getLogger(AnimalsDaoImpl.class);
private EntityManager entityManager;
public EntityManager getEntityManager() {
return entityManager;
}
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public void saveAnimal(Animal animal) {
logger.info("DAO, saving animal " +animal.getName() +" ID: " +animal.getAnimalId());
getEntityManager().persist(animal);
}
persistance.xml
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
<property name="hibernate.show_sql" value="true"/>
</properties>
</persistence-unit>
Animal class:
#Entity
#Table(name="animals")
public class Animal implements Serializable {
#Id
#Column(name = "ANIMAL_ID")
#GeneratedValue(strategy = GenerationType.AUTO)
private Integer animalId;
#Column(name = "ANIMALTYPE")
private String animalType;
#Column(name = "BREED")
private String breed;
#Column(name = "NAME")
private String name;
#Column(name = "IMAGE_1")
#Lob
private Blob image1;
#Column(name = "IMAGE_1_CONTENT_TYPE")
private String image1ContentType;
#Column(name = "IMAGE_1_FILE_NAME")
private String image1FileName;
#Column(name = "IMAGE_1_FILE_SIZE")
private String image1FileSize;
#Column(name = "IMAGE_2")
#Lob
private Blob image2;
#Column(name = "IMAGE_2_CONTENT_TYPE")
private String image2ContentType;
#Column(name = "IMAGE_2_FILE_NAME")
private String image2FileName;
#Column(name = "IMAGE_2_FILE_SIZE")
private String image2FileSize;
#Column(name = "IMAGE_3")
#Lob
private Blob image3;
#Column(name = "IMAGE_3_CONTENT_TYPE")
private String image3ContentType;
#Column(name = "IMAGE_3_FILE_NAME")
private String image3FileName;
#Column(name = "IMAGE_3_FILE_SIZE")
private String image3FileSize;
#Column(name = "ABOUT")
private String about;
#Column(name = "DATE_IN")
private Date dateIn;
#Column(name = "DATE_OUT")
private Date dateOut;
#Column(name = "STATUS")
private String status;
Got it working! Finally!
Here is a summary of the changes I had to make.
In Animal class (entity object) I changed the id field from a Integer to a long. (I doubt that was anything to do with the fix though!) and removed the implements Serializable.
In the root context I changed the tx from
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
to
<tx:annotation-driven/>
and I added
<context:component-scan base-package="com.lasthope.web"/>
Then in my servlet context I added
<context:component-scan base-package="com.lasthope.web.controllers" />
It looks like it was a clash between the compenet scans.
Why it worked while pointing to an Oracle database I will never know.
Try setting the GeneratedValue strategy to identity, make sure the ANIMAL_ID column is specified as an autonumber.
#Id
#Column(name = "ANIMAL_ID")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer animalId;
Also, if your using a new version of mySql (v5.x+), in the persistence.xml file you should specify the dialect as:
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
Try creating a transaction when persisting:
public void saveAnimal(Animal animal) {
logger.info("DAO, saving animal " +animal.getName() +" ID: " +animal.getAnimalId());
EntityManager em = getEntityManager();
em.getTransaction().begin();
em.persist(animal);
em.getTransaction().commit();
}

Implementing Spring Transactions with JAX-RS and Hibernate

Background
I am trying to implement a RESTful web service using Apache-CXF that interacts with a database to do some CRUD operations via Hibernate. The web service consumes and produces JSON formatted objects using the Jackson JAX-RS Provider.
I am currently receiving a "failed to lazily initialize a collection... no session or session was closed" exception that is bubbling up from the Jackson provider when it attempts to serialize the response object.
I assumed that if I marked the service method with #Transactional that the session would be available to the Jackson provider when it serialized the response, but that does not appear to be the case.
Question
How do I get the hibernate session to be available while Jackson is walking the object during serialization?
What I've Tried
Spring Configuration
<context:component-scan base-package="com.db.cif.mapper" />
<context:component-scan base-package="com.db.cif.mapper.repository" />
<context:annotation-config />
<tx:jta-transaction-manager>
<property name="entityManagerFactory" ref="entityManagerFactory" />
</tx:jta-transaction-manager>
<tx:annotation-driven />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="cifmapper" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
<!-- JAX-RS Configuration -->
<jaxrs:server id="mappingService" address="/">
<jaxrs:serviceBeans>
<ref bean="mappingServiceBean" />
</jaxrs:serviceBeans>
<jaxrs:extensionMappings>
<entry key="json" value="application/json" />
</jaxrs:extensionMappings>
<jaxrs:providers>
<ref bean="jsonProvider" />
</jaxrs:providers>
</jaxrs:server>
<bean id="mappingServiceBean" class="com.db.cif.mapper.MappingService" />
<bean id="jsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
Service Bean
#Service("mappingService")
#Transactional
public class MappingService
{
private static final Logger logger = Logger.getLogger(MappingService.class);
#Autowired
#Qualifier("mappingRepository")
private MappingRepository mappingRepository;
#GET
#Path("/collections/{id}")
#Produces(MediaType.APPLICATION_JSON)
public Collection getCollection(#PathParam("id") String id)
{
if(logger.isDebugEnabled())
{
logger.debug(String.format("Invoked getCollection, Collection id: %s", id));
}
return this.mappingRepository.getCollection(id);
}
#POST
#Path("/collections/")
#Consumes(MediaType.APPLICATION_JSON)
public Response addCollection(Collection collection)
{
if(logger.isDebugEnabled())
{
logger.debug(String.format("Invoked addCollection, Collection: %s", collection));
}
this.mappingRepository.createCollection(collection);
return Response.ok(collection).build();
}
}
Collection Bean
#Entity
#Table(schema = "CIFMAPPER", name = "COLLECTION")
public class Collection implements Serializable
{
private static final long serialVersionUID = 1579878442412232635L;
#Id
#Column(name = "ID")
private String id;
#Column(name = "SRC_ENDPT_ID", nullable = false, insertable = false, updatable = false)
private long sourceEndpointId;
#Column(name = "DEST_ENDPT_ID", nullable = false, insertable = false, updatable = false)
private long destinationEndpointId;
#Column(name = "DESCRIPTION")
private String description;
#Column(name = "START_DATE", nullable = false)
private Date startDate;
#Column(name = "END_DATE")
private Date endDate;
#ManyToOne(optional = false)
#JoinColumn(name = "SRC_ENDPT_ID")
private Endpoint source;
#ManyToOne(optional = false)
#JoinColumn(name = "DEST_ENDPT_ID")
private Endpoint destination;
#OneToMany(mappedBy = "collection", targetEntity = MappingGroup.class, fetch = FetchType.EAGER)
private List<MappingGroup> mappingGroups;
//Getters and Setters Removed For Brevity
}
While I believe there is a way to make that work (using a Filter or intercepetor that opens and closes the session), I think the right answer is: don't have lazy collections and proxies. Configure your mappings so that you don't have lazy collections.
An alternative approach is to manually initialize them. This is often combined with DTOs - objects with a similar structure to the entities that are used as responses to other components (so that you are not directly exposing entities). So your methods return OrderDTO rather than Order, where the DTO contains as many fields as you need to return to the caller. You manually transfer the values from the entity to the DTO.

Resources