I have a spring boot application using hibernate as it's ORM framework. It exposes a RESTful API, one of the methods inserts new messages into the table.
The problem I am having is that it performs a call to Oracle to retrieve the nextval for the sequence number, then when it inserts that it uses the first number from that pool, then when another requests comes in, it takes the value of the next nextval instead of using the next value from the initial pool. So it should go 100, 101, 102, etc... but instead it goes like that 100,200,300 (the allocation size is 100).
All the beans are singletons including the DAO that persists the messages.
#Entity
#Table(name = "MESSAGE")
public class Message implements Serializable {
#Id
#SequenceGenerator(name = "MESSAGEID_GENERATOR", sequenceName = "SEQ_MESSAGE", allocationSize = 100)
#GeneratedValue(generator = "MESSAGEID_GENERATOR", strategy = GenerationType.SEQUENCE)
#Column(name = "MESSAGEID", unique = true, nullable = false, precision = 10)
private Long messageid;
}
Dao:
#Repository
public class MessageDao {
#PersistenceContext(unitName = "ORM_Model")
private EntityManager entityManager;
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
public EntityManager getEntityManager() {
return entityManager;
}
#Transactional
public long save(Message message) {
entityManager.persist(message);
entityManager.flush();
return message.getMessageid();
}
}
persistance.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="ORM_Model">
<description>The IFIS Database Entity Model</description>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>com.package.Message</class>
<properties>
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.transaction.flush_before_completion" value="true" />
<property name="hibernate.id.new_generator_mappings" value="true" />
</properties>
</persistence-unit>
</persistence>
Any idea what could be the problem here?
Regards!
Set your allocationSize=1 to solve your issue.
Related
I am using Hibernate as an ORM for a Spring Boot Application to write values to my Postgres Database.I have configured the properties in my persistence.xml
Persistence.xml
<property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/ImageHoster" />
<property name="javax.persistence.jdbc.user" value="postgres" />
<property name="javax.persistence.jdbc.password" value="postgres" />
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
I have created an entity called Movie
Movie
#Entity
#Table(name = "Movie")
public class Movie {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
public String id;
#Column(name = "movie")
public String movie;
#Column(name = "updatedDate")
public Date updatedDate;
#Lob
#Column(name = "image")
public String image;
public String getMovie() {
return movie;
}
public void setMovie(String movie) {
this.movie = movie;
}
public Date getUpdatedDate() {
return updatedDate;
}
public void setUpdatedDate(Date updatedDate) {
this.updatedDate = updatedDate;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
}
At the first time when there is no movie table in my postgres database the table is getting created and there is no error.But as i am running the application once the table is created it is trying to create the table again which is causing the below error
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL via JDBC Statement.
My Configuration for the JPA goes like this
JPAConfig
#Configuration
public class JpaConfig {
#Bean
public EntityManagerFactory entityManagerFactory(){
LocalContainerEntityManagerFactoryBean emf =new LocalContainerEntityManagerFactoryBean();
emf.setPersistenceXmlLocation("classpath:META-INF/persistence.xml");
emf.afterPropertiesSet();
return emf.getObject();
}
#Bean
public DataSource dataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.postgresql.Driver");
ds.setUrl("jdbc:postgresql://localhost:5432/ImageHoster");
ds.setUsername("postgres");
ds.setPassword("postgres");
return ds;
}
}
Any idea where i am going wrong as I have another entity called User which is working fine and is not getting created everytime the application runs.
Once i changed the table name from Movie to movie in my entity everything was working as expected.
#Entity
#Table(name = "movie"){
}
This made everything fine..any idea why this happened? as i am not able to understand why it is a problem.
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!
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);
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();
}
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.