I want to create a table by using Hibernate + JPA. The problem is that whenever I run my code it won't create any tables. I have created already an empty database. I use Hibernate + JPA + HSQL + Maven.
Here is my persistence.xml:
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<!-- Provider of Persistence -->
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<!-- Classes, in which JPA-Annotations are read -->
<class>com.mysite.warehousebase.base.ProductData</class>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.url" value="jdbc:hsqldb:Warehouse"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
Here is my productData.java code:
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.ForeignKey;
import org.hibernate.validator.NotNull;
#Entity
#Table(name = "products")
public class ProductData extends Entityclass {
private static final long serialVersionUID = 1L;
/*
//Product Addition Time
#NotNull
#Column(name = "added", nullable = false)
private Date productAdded;*/
//Product Name
#NotNull
#Column(name = "productname", nullable = false)
private String productName;
//Product Description
#Column(name = "productdescription", nullable = true)
private String productDescription;
//Product Size
#Column(name = "productsize", nullable = true)
private String productSize;
//Product Amount
#NotNull
#Column(name = "productamount", nullable = false)
private int productAmount;
//Product Left
//Attribute to be calculated in own method
#NotNull
#Column(name = "productleft", nullable = false)
private int productLeft;
//Product buy price
#NotNull
#Column(name = "productprice", nullable = false)
private double productPrice;
//Total cost
//Attribute to be calculated in own method
#NotNull
#Column(name = "totalproductprice", nullable = false)
private double totalProductPrice;
//Product sell price
#NotNull
#Column(name = "productsellprice", nullable = false)
private double productSellPrice;
//Product sale
//Attribute to be calculated in own method
#NotNull
#Column(name = "totalsellprice", nullable = false)
private double totalSellPrice;
//Difference between cost and sale (total)
//Attribute to be calculated in own method
#NotNull
#Column(name = "buyselldifference", nullable = false)
private double buySellDifference;
//Product status; ordered, at warehouse, reserved.
//Attribute to be calculated in own method
#NotNull
#Column(name = "productstatus", nullable = false)
private String productStatus;
#Column(name = "reservedproducts", nullable = true)
private int reservedProducts;
/**
* All Setters and Getters
*
*/
/**
* #return the productName
*/
public String getProductName() {
return productName;
}
/**
* #param productName the productName to set
*/
public void setProductName(String productName) {
this.productName = productName;
}
/**
* #return the productDescription
*/
public String getProductDescription() {
return productDescription;
}
/**
* #param productDescription the productDescription to set
*/
public void setProductDescription(String productDescription) {
this.productDescription = productDescription;
}
/**
* #return the productSize
*/
public String getProductSize() {
return productSize;
}
/**
* #param productSize the productSize to set
*/
public void setProductSize(String productSize) {
this.productSize = productSize;
}
/**
* #return the productAmount
*/
public int getProductAmount() {
return productAmount;
}
/**
* #param productAmount the productAmount to set
*/
public void setProductAmount(int productAmount) {
this.productAmount = productAmount;
}
/**
* #return the productLeft
*/
public int getProductLeft() {
return productLeft;
}
/**
* #param productLeft the productLeft to set
*/
public void setProductLeft(int productLeft) {
this.productLeft = productLeft;
}
/**
* #return the productPrice
*/
public double getProductPrice() {
return productPrice;
}
/**
* #param productPrice the productPrice to set
*/
public void setProductPrice(double productPrice) {
this.productPrice = productPrice;
}
/**
* #return the totalProductPrice
*/
public double getTotalProductPrice() {
return totalProductPrice;
}
/**
* #param totalProductPrice the totalProductPrice to set
*/
public void setTotalProductPrice(double totalProductPrice) {
this.totalProductPrice = totalProductPrice;
}
/**
* #return the productSellPrice
*/
public double getProductSellPrice() {
return productSellPrice;
}
/**
* #param productSellPrice the productSellPrice to set
*/
public void setProductSellPrice(double productSellPrice) {
this.productSellPrice = productSellPrice;
}
/**
* #return the totalSellPrice
*/
public double getTotalSellPrice() {
return totalSellPrice;
}
/**
* #param totalSellPrice the totalSellPrice to set
*/
public void setTotalSellPrice(double totalSellPrice) {
this.totalSellPrice = totalSellPrice;
}
/**
* #return the buySellDifference
*/
public double getBuySellDifference() {
return buySellDifference;
}
/**
* #param buySellDifference the buySellDifference to set
*/
public void setBuySellDifference(double buySellDifference) {
this.buySellDifference = buySellDifference;
}
/**
* #return the productStatus
*/
public String getProductStatus() {
return productStatus;
}
/**
* #param productStatus the productStatus to set
*/
public void setProductStatus(String productStatus) {
this.productStatus = productStatus;
}
/**
* #return the reservedProducts
*/
public int getReservedProducts() {
return reservedProducts;
}
/**
* #param reservedProducts the reservedProducts to set
*/
public void setReservedProducts(int reservedProducts) {
this.reservedProducts = reservedProducts;
}
/**
* #return the productSection
*/
public ProductSection getProductSection() {
return productSection;
}
/**
* #param productSection the productSection to set
*/
public void setProductSection(ProductSection productSection) {
this.productSection = productSection;
}
public ProductData(){
}
public ProductData(String productName){
this.productName = productName;
}
}
And my main.java code:
public static void main(String[] args) {
DataStructureTest testProduct = new DataStructureTest();
testProduct.testProductData();
}
What is wrong? Why Hibernate won't create a table that is needed? I have tried using hibernate.hbm2ddl.auto with value of "update". It won't help.
Can you try with
<property name="hibernate.hbm2ddl.auto" value="create"/>
Also 'transaction-type="RESOURCE_LOCAL" is defined in the persistence xml
I found the solution for this. For some reason value of
property name="hibernate.connection.url" value="jdbc:hsqldb:Warehouse"
won't work. So instead of what I did was that I created a database connection which value was following
jdbc:hsqldb:file:[folder name]
This folder name is user defined. So the new code of that particular line would be:
property name="hibernate.connection.url" value="jdbc:hsqldb:file:[folder name]"
Now everything is running smoothly and tables are created and updated :).
Related
I have a simple relationship as shown in the diagram above.
I can persist this using the following Hibernate Mapping:
<class name="Strategy" table="Strategy">
<id name="id" column="StrategyId" unsaved-value="any">
<generator class="identity"/>
</id>
<property name="status" column="Status"/>
</class>
<class name="Alert" table="Alert">
<id name="id" column="AlertId">
<generator class="identity"/>
</id>
<property name="name" column="Name"/>
</class>
<class name="StrategyAlert" table="StrategyAlert">
<composite-id>
<key-many-to-one name="strategy" class="Strategy" column="StrategyId"/>
<key-many-to-one name="alert" class="Alert" column="AlertId"/>
</composite-id>
<property name="nominal" column="Nominal"/>
</class>
I am having a really hard time trying to figure out how to do this using Annotations in JPA 1.0.
Here's what I've got so far:
Alert Class:
#Entity
#Table(name="ALERT")
public class Alert implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="ALERTID")
private int id;
#Column(name="NAME")
private String name;
}
Strategy Class:
#Entity
#Table(name="STRATEGY")
public class Strategy implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="STRATEGYID")
private int id;
#Column(name="STATUS")
private String status;
}
StrategyAlertPK class:
public class StrategyAlertPK implements Serializable {
private int strategyId;
private int alertId;
}
StrategyAlert class:
#Entity
#Table(name="STRATEGYALERT")
#IdClass(StrategyAlertPK.class)
public class StrategyAlert implements Serializable {
#Id
#Column(name="STRATEGYID")
private int strategyId;
#Id
#Column(name="ALERTID")
private int alertId;
#ManyToOne
#JoinColumn(name="STRATEGYID", insertable=false, updatable=false)
private Strategy strategy;
#ManyToOne
#JoinColumn(name="ALERTID", insertable=false, updatable=false)
private Alert alert;
#Column
private String nominal;
}
Test Case:
em.getTransaction().begin();
Alert alert = new Alert();
alert.setName("NAME");
em.persist(alert);
Strategy strategy = new Strategy();
strategy.setStatus("STATUS");
em.persist(strategy);
StrategyAlert strategyAlert = new StrategyAlert();
strategyAlert.setAlert(alert);
strategyAlert.setStrategy(strategy);
strategyAlert.setNominal("NOMINAL");
em.persist(strategyAlert);
em.getTransaction().commit();
I'm getting the following error:
Referential integrity constraint violation: "FK80432DA9CE00672E: PUBLIC.STRATEGYALERT FOREIGN KEY(STRATEGYID) REFERENCES PUBLIC.STRATEGY(STRATEGYID) (0)
I'm using <property name="hibernate.hbm2ddl.auto" value="create" /> to generate the tables.
How do I annotate the StrategyAlert class correctly?
Take a look at this questions: How to implement a complex many to many relationship in JPA?
I think the problem here is you have to join the Id declaration and the manyToOne declaration as described in JPA 1, I can´t test the code right now, but more or less it has to be like this
#Entity
#Table(name="STRATEGYALERT")
#IdClass(StrategyAlertPK.class)
public class StrategyAlert implements Serializable {
#Id
#ManyToOne
#JoinColumn(name="STRATEGYID", insertable=false, updatable=false)
private Strategy strategy;
#Id
#ManyToOne
#JoinColumn(name="ALERTID", insertable=false, updatable=false)
private Alert alert;
#Column
private String nominal;
// TODO Getters and setters
}
UPDATE
Hi,
now I can test the code, and is working for m with the following code (some minors corrections):
/**
*
*/
package hib;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
#Entity
#Table(name="ALERT")
public class Alert implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="ALERTID")
private int id;
#Column(name="NAME")
private String name;
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
}
Strategy
/**
*
*/
package hib;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
#Entity
#Table(name="STRATEGY")
public class Strategy implements Serializable {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
#Column(name="STRATEGYID")
private int id;
#Column(name="STATUS")
private String status;
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the status
*/
public String getStatus() {
return status;
}
/**
* #param status the status to set
*/
public void setStatus(String status) {
this.status = status;
}
}
StrategyAlertPK
/**
*
*/
package hib;
import java.io.Serializable;
import javax.persistence.Embeddable;
/**
*
*/
#Embeddable
public class StrategyAlertPK implements Serializable {
#ManyToOne
private Strategy strategy;
#ManyToOne
private Alert alert;
/**
* #return the strategy
*/
public Strategy getStrategy() {
return strategy;
}
/**
* #param strategy the strategy to set
*/
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
/**
* #return the alert
*/
public Alert getAlert() {
return alert;
}
/**
* #param alert the alert to set
*/
public void setAlert(Alert alert) {
this.alert = alert;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
StrategyAlertPK that = (StrategyAlertPK) o;
if (strategy != null ? !strategy.equals(that.strategy) : that.strategy != null) {
return false;
}
if (alert != null ? !alert.equals(that.alert) : that.alert != null) {
return false;
}
return true;
}
public int hashCode() {
int result;
result = (strategy != null ? strategy.hashCode() : 0);
result = 31 * result + (alert != null ? alert.hashCode() : 0);
return result;
}
}
StrategyAlert
/**
*
*/
package hib;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
*
*/
#Entity
#Table(name="STRATEGYALERT")
#AssociationOverrides({ #AssociationOverride(name = "pk.strategy", joinColumns = #JoinColumn(name = "STRATEGYID")),
#AssociationOverride(name = "pk.alert", joinColumns = #JoinColumn(name = "ALERTID")) })
public class StrategyAlert implements Serializable {
#EmbeddedId
private StrategyAlertPK pk = new StrategyAlertPK();
#Column
private String nominal;
#Transient
public Strategy getStrategy() {
return pk.getStrategy();
}
public void setStrategy(Strategy strategy) {
pk.setStrategy(strategy);
}
#Transient
public Alert getAlert() {
return pk.getAlert();
}
public void setAlert(Alert alert) {
pk.setAlert(alert);
}
/**
* #return the nominal
*/
public String getNominal() {
return nominal;
}
/**
* #param nominal the nominal to set
*/
public void setNominal(String nominal) {
this.nominal = nominal;
}
}
With that code your test is running OK (I tested it with JPA 1.0.1, Hibernate 3.3.1.GA and spring 2.5.5). I am using H2 as memory database so I had to change Identity to AUTO in generated values, maybe you don´t need to do that.
Hope helps!
I have found a solution but I don't think this is the correct way to do it.
I have a static nested class for the ID. Then in both setter methods I also set the ID. This seems a very manual way to do it and surely there must be a better way?
#Entity
#Table(name="STRATEGYALERT")
public class StrategyAlert {
#Embeddable
public static class Id implements Serializable {
private static final long serialVersionUID = -8270591004786497335L;
#Column(name="STRATEGYID")
private int strategyId;
#Column(name="ALERTID")
private int alertId;
public Id() {}
public Id(int strategyId, int alertId) {
this.strategyId = strategyId;
this.alertId = alertId;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + alertId;
result = prime * result + strategyId;
return result;
}
#Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
Id other = (Id)obj;
if(alertId != other.alertId)
return false;
if(strategyId != other.strategyId)
return false;
return true;
}
}
#EmbeddedId
private Id id = new Id();
#ManyToOne
#JoinColumn(name="STRATEGYID", insertable=false, updatable=false)
private Strategy strategy;
#ManyToOne
#JoinColumn(name="ALERTID", insertable=false, updatable=false)
private Alert alert;
#Column(name="NOMINAL")
private String nominal;
public StrategyAlert() {}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
// SET ID
this.id.strategyId = strategy.getId();
}
public void setAlert(Alert alert) {
this.alert = alert;
// SET ID
this.id.alertId = alert.getId();
}
// Other Getters & Setters...
}
Based on an archetype i created a java ee app. There is an included arquillian test that runs fine. it just calls a method on a #Stateless bean that persists an pre-made entity.
now i added some entity with some relations and i wrote a test for them. But on peristing any entity i get
Transaction is required to perform this operation (either use a transaction or extended persistence context)
I think i need to mark the testmethod with #Transactional but it seems not to be in class path.
Manually invoking the transaction on injected EntityManager yields another error.
So how to correctly setup such tests and dependencies.
EDIT As Grzesiek D. suggested here are some details. this is the entity (the one thta links others):
#Entity
public class Booking implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* internal id.
*/
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
/**
* Used for optimistic locking.
*/
#Version
#Column(name = "version")
private int version;
/**
* A booking must have a project related.
*/
#ManyToOne
#JoinColumn(name = "project_id")
#NotNull
private Project project;
/**
* A booking must have an owner.
*/
#ManyToOne
#JoinColumn(name = "user_id")
#NotNull
private User owner;
/**
* A booking always has a start time.
*/
#Column
#NotNull
private Timestamp start;
/**
* A booking always has an end time.
*/
#Column
#NotNull
private Timestamp end;
/**
*
* #return true if start is befor end. false otherwise (if equal or after end).
*/
#AssertTrue(message = "Start must before end.")
public final boolean isStartBeforeEnd() {
return start.compareTo(end) < 0;
}
/**
* #return the id
*/
public final Long getId() {
return id;
}
/**
* #param id
* the id to set
*/
public final void setId(final Long id) {
this.id = id;
}
/**
* #return the version
*/
public final int getVersion() {
return version;
}
/**
* #param version
* the version to set
*/
public final void setVersion(final int version) {
this.version = version;
}
/**
* #return the project
*/
public final Project getProject() {
return project;
}
/**
* #param project
* the project to set
*/
public final void setProject(final Project project) {
this.project = project;
}
/**
* #return the owner
*/
public final User getOwner() {
return owner;
}
/**
* #param owner
* the owner to set
*/
public final void setOwner(final User owner) {
this.owner = owner;
}
/**
* #return the start
*/
public final Timestamp getStart() {
return start;
}
/**
* #param start
* the start to set
*/
public final void setStart(final Timestamp start) {
this.start = start;
}
/**
* #return the end
*/
public final Timestamp getEnd() {
return end;
}
/**
* #param end
* the end to set
*/
public final void setEnd(final Timestamp end) {
this.end = end;
}
//hashCode, equals, toString omitted here
}
Here is the test:
#RunWith(Arquillian.class)
public class BookingTest {
#Deployment
public static Archive<?> createDeployment() {
return ArquillianContainer.addClasses(Resources.class, Booking.class, Project.class, User.class);
}
#Inject
private EntityManager em;
#Test
public void createBooking() {
Booking booking = new Booking();
booking.setStart(new Timestamp(0));
booking.setEnd(new Timestamp(2));
User user = new User();
user.setName("Klaus");
booking.setOwner(user);
Project project = new Project();
project.setName("theOne");
project.setDescription("blub");
booking.setProject(project);
em.persist(booking);
System.out.println("here");
}
}
And here the exception:
javax.persistence.TransactionRequiredException: JBAS011469: Transaction is required to perform this operation (either use a transaction or extended persistence context)
I know it will work if i create a #Stateless bean and encapsulate the persist there but i want a direct test of entity's validation and i need a playground to evolve the data model.
In order to have transaction support in Arquillian tests you will need to bring in extension which enables this feature. In your case jta dependency should do the job.
<dependency>
<groupId>org.jboss.arquillian.extension</groupId>
<artifactId>arquillian-transaction-jta</artifactId>
<scope>test</scope>
</dependency>
In addition, if you are using JBoss, you will need to provide its JNDI for UserTranscation, so put following section in your arquillian.xml:
<?xml version="1.0" ?>
<arquillian xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://jboss.org/schema/arquillian" xsi:schemaLocation="http://jboss.org/schema/arquillian
http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
<extension qualifier="transaction">
<property name="manager">java:jboss/UserTransaction</property>
</extension>
</arquillian>
This way you can use #Transactional which comes from this extension's API.
Unworking case:
In the unworking case the method always returns bean with null values in
table:
int- matrix_id; int user_id; varchar(45) matrix_name; int matrix_length;
MatrixDAO:
package com.calango.DAOLayer.DAO;
import com.calango.DAOLayer.model.Matrix;
/**
*
* #author Calango
*/
public interface MatrixDAO {
public Matrix findByID(int id);
public String findMatrixNameById(int matrixId);
public int getMatrixLength(int matrix_id);
public void insertRecord(Matrix inserObject);
public int findIdByName(String matrixName);
}
JdbcMatrixDAO:
package com.calango.DAOLayer.DAO.impl;
import com.calango.DAOLayer.DAO.MatrixDAO;
import com.calango.DAOLayer.model.Matrix;
import javax.sql.DataSource;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
/**
*
* #author Calango
*/
public class JdbcMatrixDAO implements MatrixDAO{
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
public Matrix findByID(int matrixId) {
String sqlForID = "SELECT * FROM matrix WHERE matrix_id = ?";
jdbcTemplate = new JdbcTemplate(dataSource);
Matrix matrix = (Matrix)jdbcTemplate.queryForObject(
sqlForID, new Object[] { matrixId },
new BeanPropertyRowMapper(Matrix.class));
return matrix;
}
#Override
public String findMatrixNameById(int matrixId){return findByID(matrixId).getMatrixName();}
#Override
public int getMatrixLength(int matrixId){return findByID(matrixId).getMatrixLength();}
#Override
public void insertRecord(Matrix insertObject) {
String insertMatrix = "INSERT INTO matrix (user_id, matrix_name, matrix_length) VALUES (?, ?, ?)";
jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update(insertMatrix, new Object[] { insertObject.getUserId(),
insertObject.getMatrixName(),insertObject.getMatrixLength()
});
}
#Override
public int findIdByName(String matrixName) {
String sqlForName = "SELECT matrix_id FROM matrix WHERE matrix_name = ?";
jdbcTemplate = new JdbcTemplate(dataSource);
Matrix matrix = (Matrix)jdbcTemplate.queryForObject(
sqlForName, new Object[] { matrixName },
new BeanPropertyRowMapper(Matrix.class));
return matrix.getMatrixId();
}
}
Spring-database.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>config.properties</value>
</property>
</bean>
<bean id="historyDAO" class="com.calango.DAOLayer.DAO.impl.JdbcHistoryDAO">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="elementsDAO" class="com.calango.DAOLayer.DAO.impl.JdbcElementsDAO">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="matrixDAO" class="com.calango.DAOLayer.DAO.impl.JdbcMatrixDAO">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${DB_DRIVER}" />
<property name="url" value="${DB_CONNECTION}" />
<property name="username" value="${DB_USER}" />
<property name="password" value="${DB_PASSWORD}" />
</bean>
</beans>
I'm calling:
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-database.xml");
int matrixID = 4;
JdbcMatrixDAO matrixDAO = (JdbcMatrixDAO) context.getBean("matrixDAO");
String matrixName = matrixDAO.findMatrixNameById(matrixID);
Matrix
package com.calango.DAOLayer.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
* #author Calango
*/
#Entity
#Table(name="matrix")
public class Matrix implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "matrix_id", nullable = false)
int matrixId;
#Column(name = "user_id")
int userId;
#Column(name = "matrix_name")
String matrixName;
#Column(name = "matrix_length")
int matrixLength;
public Matrix(){}
public Matrix(int matrixId, int userId, String matrixName, int matrixLength){
this.matrixId = matrixId;
this.userId = userId;
this.matrixName = matrixName;
this.matrixLength = matrixLength;
}
public int getMatrixId() {
return matrixId;
}
public int getUserId() {
return userId;
}
public String getMatrixName() {
return matrixName;
}
public int getMatrixLength() {
return matrixLength;
}
}
working case
history
package com.calango.DAOLayer.model;
import java.io.Serializable;
import java.sql.Timestamp;
import javax.persistence.*;
/**
*
* #author Calango
*/
#Entity
#Table(name="history")
public class History implements Serializable{
private static final long serialVersionUID = 1L;
#Id
#Column(name = "history_id", nullable = false)
int historyId;
#Column(name = "matrix1_id")
int matrix1Id;
#Column(name = "matrix2_id")
int matrix2Id;
#Column(name = "matrix_result_id")
int matrixResultId;
#Column(name = "date")
#Temporal(TemporalType.TIMESTAMP)
Timestamp date;
public History(){}
public History
(int historyId, int matrix1ID, int matrix2ID,
int matrixResultID, Timestamp date) {
this.historyId = historyId;
this.matrix1Id = matrix1ID;
this.matrix2Id = matrix2ID;
this.matrixResultId = matrixResultID;
this.date = date;
}
public int getHistoryId() {
return historyId;
}
public int getMatrix1Id() {
return matrix1Id;
}
public int getMatrix2Id() {
return matrix2Id;
}
public int getMatrixResultId() {
return matrixResultId;
}
public Timestamp getDate() {
return date;
}
public void setHistoryId(int historyId) {
this.historyId = historyId;
}
public void setMatrix1Id(int matrix1Id) {
this.matrix1Id = matrix1Id;
}
public void setMatrix2Id(int matrix2Id) {
this.matrix2Id = matrix2Id;
}
public void setMatrixResultId(int matrixResultId) {
this.matrixResultId = matrixResultId;
}
public void setDate(Timestamp date) {
this.date = date;
}
}
HistoryDAO
package com.calango.DAOLayer.DAO;
import com.calango.DAOLayer.model.History;
import java.util.List;
/**
*
* #author Calango
*/
public interface HistoryDAO {
public History findByID(int id);
public int findIdByDate(String date);
public List<String> getDatesList();
public void insertHistory(History insertObject);
}
JdbcHistoryDAO
package com.calango.DAOLayer.DAO.impl;
import com.calango.DAOLayer.DAO.HistoryDAO;
import com.calango.DAOLayer.model.History;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
/**
*
* #author Calango
*/
public class JdbcHistoryDAO implements HistoryDAO{
private DataSource dataSource;
private JdbcTemplate jdbcTemplate;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
public History findByID(int historyId) {
String sqlForID = "SELECT * FROM history WHERE history_id = ?";
jdbcTemplate = new JdbcTemplate(dataSource);
History history = (History)jdbcTemplate.queryForObject(
sqlForID, new Object[] { historyId },
new BeanPropertyRowMapper(History.class));
return history;
}
#Override
public int findIdByDate(String date) {
try{
String sqlForDate = "SELECT * FROM history WHERE date = ?";
jdbcTemplate = new JdbcTemplate(dataSource);
History history = (History)jdbcTemplate.queryForObject(
sqlForDate, new Object[] { date },
new BeanPropertyRowMapper(History.class));
return history.getMatrix1Id();
}catch(EmptyResultDataAccessException ex){
System.out.println("No date has been found: "+date);
return 1;
}
//Logger.getLogger(JdbcHistoryDAO.class.getName()).log(Level.SEVERE, null, "No id was found by this date");
}
#Override
public List<String> getDatesList(){
String sqlForDates = "SELECT date FROM history";
jdbcTemplate = new JdbcTemplate(dataSource);
List<String> dates =
(List<String>)jdbcTemplate.queryForList(sqlForDates,String.class);
return dates;
}
#Override
public void insertHistory(History insertObject) {
String insertHistorySql = "INSERT INTO history (matrix1_id, matrix2_id, matrix_result_id, date) VALUES(?, ?, ?, NOW())";
jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.update(insertHistorySql, new Object[] { insertObject.getMatrix1Id(),
insertObject.getMatrix2Id(),insertObject.getMatrixResultId()
});
}
}
calling
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-database.xml");
JdbcHistoryDAO historyDAO = (JdbcHistoryDAO) context.getBean("historyDAO");
String selectedDate = "2014-05-01 16:10:09.0";
int matrixID = historyDAO.findIdByDate(selectedDate);
I have this problem that i can't solve, this is my entity class:
/**
* #hibernate.class
* table="users.network_topic"
* #hibernate.cache usage="read-write"
*/
public class NetworkTopic implements Serializable, Idable{
/** identifier field */
private Long id;
/** persistent field */
private Long networkId;
/** persistent field */
private Long topicId;
private UserTopic topic;
private Network network;
/**
* #hibernate.id
* generator-class="assigned"
* type="java.lang.Long"
* column="id"
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* #hibernate.property
* type="java.lang.Long"
* column="network_id"
* not-null="true"
*/
public Long getNetworkId() {
return networkId;
}
public void setNetworkId(Long networkId) {
this.networkId = networkId;
}
/**
* #hibernate.property
* type="java.lang.Long"
* column="user_topic_id"
* not-null="true"
*/
public Long getTopicId() {
return topicId;
}
public void setTopicId(Long topicId) {
this.topicId = topicId;
}
/**
* #hibernate.set
* lazy="true"
* inverse="true"
* cascade="none"
* #hibernate.key
* column="user_topic_id"
* #hibernate.one-to-many
* class="com.netblue.matchpoint.domain.UserTopic"
*
*/
public UserTopic getTopic() {
return topic;
}
public void setTopic(UserTopic topic) {
this.topic = topic;
}
/**
* #hibernate.set
* lazy="true"
* inverse="true"
* cascade="none"
* #hibernate.key
* column="network_id"
* #hibernate.one-to-many
* class="com.netblue.matchpoint.domain.Network"
*
*/
public Network getNetwork() {
return network;
}
public void setNetwork(Network network) {
this.network = network;
}
#Override
public String toString() {
return "Network[id=" + id + "]";
}
}
Then i try to save a new register with this code:
UserTopic topic = new UserTopic();
topic.setId(topicId);
topic.setName(ParseUtil.getString(map.get(MPConstants.TOPIC_NAME_PARAM)));
topic.setCreatedBy(ParseUtil.getInt(map.get(MPConstants.USER_ID)));
Date now = new Date();
topic.setCreatedDt(now);
topic.setLastUpdatedDt(now);
topic.setStatusId(Status.ACTIVE);
topic.setActivityCnt(0);
userTopicDao.saveOrUpdate(topic);
UserTopicMap utm = new UserTopicMap();
utm.setId(topicId);
utm.setMtid(topicId);
utm.setOtid(topicId);
utm.setIsDeleted(false);
utm.setLastUpdatedDt(now);
userTopicMapDao.saveOrUpdate(utm);
Network network = MpAuctionUtil.getNetworkById(networkId);
NetworkTopic networkTopic = new NetworkTopic();
networkTopic.setNetworkId(networkId);
networkTopic.setTopicId(topicId);
networkTopic.setNetwork(network);
networkTopic.setTopic(topic);
LOG.debug("userTopicService addObjSubscriber x networkId="+networkId+", topicId="+topicId);
networkTopicDao.saveOrUpdate(networkTopic);
The last lines are the ones that fail, if i remove them it works, i mean it saves topics ok, but when i try to do this it fail, i don't know if i'm doing something wrong, please help me !!
The NetworkTopic class hasnt been assigned an id. you must use the setId method or consider consider one of the other id strategies
2.2.3.1. Generating the identifier property
NetworkTopic networkTopic = new NetworkTopic();
networkTopic.setNetworkId(networkId);
networkTopic.setTopicId(topicId);
networkTopic.setNetwork(network);
networkTopic.setTopic(topic);
LOG.debug("userTopicService addObjSubscriber x networkId="+networkId+", topicId="+topicId);
networkTopicDao.saveOrUpdate(networkTopic);
Here,you must call the method setId, and set the value manually, because your id generator is "assigned", and that means you must assigned manually every time before you insert or update your data!
I am not very experienced with Hibernate and I am trying to create one-to-many mapping.
Here are relevant tables:
And here are my mapping files:
<hibernate-mapping package="com.xorty.mailclient.server.domain">
<class name="Attachment" table="Attachment">
<id name="id">
<column name="idAttachment"></column>
</id>
<property name="filename">
<column name="name"></column>
</property>
<property name="blob">
<column name="file"></column>
<type name="blob"></type>
</property>
<property name="mailId">
<column name="mail_idmail"></column>
</property>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="com.xorty.mailclient.server.domain.Mail" table="mail">
<id name="id" type="integer" column="idmail"></id>
<property name="content">
<column name="body"></column>
</property>
<property name="ownerAddress">
<column name="account_address"></column>
</property>
<property name="title">
<column name="head"></column>
</property>
<set name="receivers" table="mail_has_contact" cascade="all">
<key column="mail_idmail"></key>
<many-to-many column="contact_address" class="com.xorty.mailclient.client.domain.Contact"></many-to-many>
</set>
<bag name="attachments" cascade="save-update, delete" inverse="true">
<key column="mail_idmail" not-null="true"/>
<one-to-many class="com.xorty.mailclient.server.domain.Attachment"/>
</bag>
</class>
</hibernate-mapping>
In plain english, one mail has more attachments.
When I try to do CRUD on mail without attachments, everyting works just fine. When I add some attachment to mail, I cannot perform any CRUD operation.
I end up with following trace:
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:268)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at domain.DatabaseTest.testPersistMailWithAttachment(DatabaseTest.java:355)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.sql.BatchUpdateException: Cannot add or update a child row: a foreign key constraint fails (`maildb`.`attachment`, CONSTRAINT `fk_Attachment_mail1` FOREIGN KEY (`mail_idmail`) REFERENCES `mail` (`idmail`) ON DELETE NO ACTION ON UPDATE NO ACTION)
at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1666)
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1082)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 27 more
Thank you
EDIT: On hvgotcodes proposal:
package com.xorty.mailclient.server.domain;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.xorty.mailclient.client.domain.Account;
import com.xorty.mailclient.client.domain.AttachmentDTO;
import com.xorty.mailclient.client.domain.Contact;
import com.xorty.mailclient.client.domain.MailDTO;
/**
* Heavy weight Hibernate Mail
* #author MisoV
* #version 0.1
*/
public class Mail implements Serializable {
private List<Attachment> attachments = new ArrayList<Attachment>();
private String content;
private int id;
private boolean isNew;
private Account owner;
private String ownerAddress;
private Set<Contact> receivers = new HashSet<Contact>();
private String sender;
private String title;
/**
* Hibernate purposes
*/
public Mail() { // $codepro.audit.disable
}
/**
* Unwraps light DTO object to heavy Hibernate object.
* #param dto Corresponding DTO class.
*/
public Mail(final MailDTO dto) {
for (final AttachmentDTO attachmentDTO : dto.getAttachments()) {
attachments.add(new Attachment(attachmentDTO));
}
content = dto.getContent();
id = dto.getId();
isNew = dto.isNew();
owner = dto.getOwner();
ownerAddress = dto.getOwnerAddress();
receivers = dto.getReceivers();
sender = dto.getSender();
title = dto.getTitle();
}
/**
* Inserts new attachment
* #param attachment
*/
public void addAttachment(final Attachment attachment) {
attachments.add(attachment);
}
/* (non-Javadoc)
* #see java.lang.Object#equals(java.lang.Object)
*/
#Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof Mail)) {
return false;
}
final Mail other = (Mail) obj;
if (attachments == null) {
if (other.attachments != null) {
return false;
}
} else if (!attachments.equals(other.attachments)) {
return false;
}
if (content == null) {
if (other.content != null) {
return false;
}
} else if (!content.equals(other.content)) {
return false;
}
if (id != other.id) {
return false;
}
if (isNew != other.isNew) {
return false;
}
if (owner == null) {
if (other.owner != null) {
return false;
}
} else if (!owner.equals(other.owner)) {
return false;
}
if (ownerAddress == null) {
if (other.ownerAddress != null) {
return false;
}
} else if (!ownerAddress.equals(other.ownerAddress)) {
return false;
}
if (receivers == null) {
if (other.receivers != null) {
return false;
}
} else if (!receivers.equals(other.receivers)) {
return false;
}
if (sender == null) {
if (other.sender != null) {
return false;
}
} else if (!sender.equals(other.sender)) {
return false;
}
if (title == null) {
if (other.title != null) {
return false;
}
} else if (!title.equals(other.title)) {
return false;
}
return true;
}
/**
* #return the attachments
*/
public List<Attachment> getAttachments() {
return attachments;
}
/**
* #return the content
*/
public String getContent() {
return content;
}
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #return the owner
*/
public Account getOwner() {
return owner;
}
/**
* #return the ownerAddress
*/
public String getOwnerAddress() {
return ownerAddress;
}
/**
* #return the receivers
*/
public Set<Contact> getReceivers() {
return receivers;
}
/**
* #return the sender
*/
public String getSender() {
return sender;
}
/**
* #return the title
*/
public String getTitle() {
return title;
}
/* (non-Javadoc)
* #see java.lang.Object#hashCode()
*/
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((attachments == null) ? 0 : attachments.hashCode());
result = prime * result + ((content == null) ? 0 : content.hashCode());
result = prime * result + id;
result = prime * result + (isNew ? 1231 : 1237);
result = prime * result + ((owner == null) ? 0 : owner.hashCode());
result = prime * result
+ ((ownerAddress == null) ? 0 : ownerAddress.hashCode());
result = prime * result
+ ((receivers == null) ? 0 : receivers.hashCode());
result = prime * result + ((sender == null) ? 0 : sender.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
}
/**
* #return the isNew
*/
public boolean isNew() {
return isNew;
}
/**
* #param attachments the attachments to set
*/
public void setAttachments(final List<Attachment> attachments) {
this.attachments = attachments;
}
/**
* #param content the content to set
*/
public void setContent(final String content) {
this.content = content;
}
/**
* #param id the id to set
*/
public void setId(final int id) {
this.id = id;
}
/**
* #param isNew the isNew to set
*/
public void setNew(final boolean isNew) {
this.isNew = isNew;
}
/**
* #param owner the owner to set
*/
public void setOwner(final Account owner) {
this.owner = owner;
}
/**
* #param ownerAddress the ownerAddress to set
*/
public void setOwnerAddress(final String ownerAddress) {
this.ownerAddress = ownerAddress;
}
/**
* #param receivers the receivers to set
*/
public void setReceivers(final Set<Contact> receivers) {
this.receivers = receivers;
}
/**
* #param sender the sender to set
*/
public void setSender(final String sender) {
this.sender = sender;
}
/**
* #param title the title to set
*/
public void setTitle(final String title) {
this.title = title;
}
}
Attachment:
// $codepro.audit.disable com.instantiations.assist.eclipse.analysis.audit.rule.effectivejava.alwaysOverridetoString.alwaysOverrideToString
/**
*
*/
package com.xorty.mailclient.server.domain;
import java.io.Serializable;
import java.sql.SQLException;
import javax.sql.rowset.serial.SerialBlob;
import javax.sql.rowset.serial.SerialException;
import com.xorty.mailclient.client.domain.AttachmentDTO;
/**
* Heavy weight Hibernate Attachment
* #author MisoV
* #version 0.1
*/
public class Attachment implements Serializable {
private static final long serialVersionUID = 2047475939737947104L;
private SerialBlob blob;
private byte[] content;
private String contentid;
private String contenttype;
private String filename;
private int id;
private int mailId;
/**
* Hibernate purposes
*/
public Attachment() { // $codepro.audit.disable emptyMethod
}
/**
* Unwraps DTO to heavy weight hibernate object.
* #param dto
*/
public Attachment(final AttachmentDTO dto) {
content = dto.getContent();
contentid = dto.getContentid();
contenttype = dto.getContenttype();
filename = dto.getFilename();
id = dto.getId();
mailId = dto.getMailId();
try {
blob = new SerialBlob(content);
} catch (final SerialException e) {
e.printStackTrace();
} catch (final SQLException e) {
e.printStackTrace();
}
}
/**
* #return the blob
*/
public SerialBlob getBlob() {
return blob;
}
/**
* #return the content
*/
public byte[] getContent() {
return content;
}
/**
* #return the contentid
*/
public String getContentid() {
return contentid;
}
/**
* #return the contenttype
*/
public String getContenttype() {
return contenttype;
}
/**
* #return the filename
*/
public String getFilename() {
return filename;
}
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #return the mailId
*/
public int getMailId() {
return mailId;
}
/**
* #param blob the blob to set
*/
public void setBlob(final SerialBlob blob) {
this.blob = blob;
}
/**
* #param content the content to set
*/
public void setContent(final byte[] content) {
this.content = content;
}
/**
* #param contentid the contentid to set
*/
public void setContentid(final String contentid) {
this.contentid = contentid;
}
/**
* #param contenttype the contenttype to set
*/
public void setContenttype(final String contenttype) {
this.contenttype = contenttype;
}
/**
* #param filename the filename to set
*/
public void setFilename(final String filename) {
this.filename = filename;
}
/**
* #param id the id to set
*/
public void setId(final int id) {
this.id = id;
}
/**
* #param mailId the mailId to set
*/
public void setMailId(final int mailId) {
this.mailId = mailId;
}
}
EDIT2:
Hibernate actually performs insert:
insert into Attachment (name, file, mail_idmail, idAttachment) values (?, ?, ?, ?)
And values are correctly set. It doesn't fail on session.save nor on session.get (it even gets correct copy). It fails on committing transaction.
Only thing I can get of it is: Cannot add or update a child row: a foreign key constraint fails (maildb.attachment, CONSTRAINTfk_Attachment_mail1FOREIGN KEY (mail_idmail) REFERENCESmail(idmail) ON DELETE NO ACTION ON UPDATE NO ACTION)
you are getting a constraint violation exception. I think it is on the foreign key from attachment to mail, as evidenced by
foreign key constraint fails (`maildb`.`attachment`, CONSTRAINT `fk_Attachment_mail1` FOREIGN KEY (`mail_idmail`)
I noticed you are not specifying a generator for your id. See this documentation
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/mapping.html#mapping-declaration-id
since you did not specify the generator, the default is 'assigned' which means you have to programmatically assign the ids to the objects before you save them, which might or might not be what you want.
You didn't show us the code for how your Mail entity relates to the Attachment entity, or how you create your entities, which would all me to help more...depending on how you do it, hibernate might or might not be able to assign the foreign key in the attachment class.
EDIT -- from your comments, you are missing a few things. Try assigning the id of the mail entity to the attachment in your addAttachment method on mail. If you want the db to assign the id, you need to look up how to have the id column of the tables auto-increment for whatever RDBMS system you are using, and then you change add a generator to the id mappings of the entities. The generator will probably be 'identity' or 'increment' depending on the RDBMS.
As you want to make a bi-directionnal relation, you should indicate to your Attachment the Mail object and not only the Id :
In the Attcahment class, remove
private int mailId;
and replace it by
private Mail mail;
with the correct setter and getter.
In the Xml mapping file:
<property name="mailId">
<column name="mail_idmail"></column>
</property>
should be replaced by :
<many-to-one name="mail"
column="mail_idmail" not-null="true"/>
By the way, your hashCode/equals methods are crap.
You should read this : http://community.jboss.org/wiki/EqualsandHashCode
Anyway, it's better to not override them than have them wrong.