diff --git a/core/src/main/java/org/hibernate/cfg/AnnotationBinder.java b/core/src/main/java/org/hibernate/cfg/AnnotationBinder.java index 1109113ed2..6ca2259f22 100644 --- a/core/src/main/java/org/hibernate/cfg/AnnotationBinder.java +++ b/core/src/main/java/org/hibernate/cfg/AnnotationBinder.java @@ -1412,6 +1412,33 @@ public final class AnnotationBinder { final XAnnotatedElement element = propertyAnnotatedElement.getProperty(); if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) { annElts.add( 0, propertyAnnotatedElement ); + /** + * The property must be put in hibernate.properties as it's a system wide property. Fixable? + * TODO support true/false/default on the property instead of present / not present + * TODO is @Column mandatory? + * TODO add method support + * TODO avoid custId hardcoded + */ + if ( System.getProperty( "hibernate.enable_specj_proprietary_syntax" ) != null ) { + if ( element.isAnnotationPresent( Id.class ) && element.isAnnotationPresent( Column.class ) ) { + String columnName = element.getAnnotation( Column.class ).name(); + for ( XProperty prop : declaringClass.getDeclaredProperties( AccessType.FIELD.getType() ) ) { + if ( prop.isAnnotationPresent( JoinColumn.class ) + && prop.getAnnotation( JoinColumn.class ).name().equals( columnName ) + && !prop.isAnnotationPresent( MapsId.class ) ) { + //create a PropertyData fpr the specJ property holding the mapping + PropertyData specJPropertyData = new PropertyInferredData( + declaringClass, //same dec + prop, // the actual @XToOne property + propertyAccessor, //TODO we should get the right accessor but the same as id would do + mappings.getReflectionManager() + ); + mappings.addPropertyAnnotatedWithMapsIdSpecj( entity, specJPropertyData, "custId" ); + } + } + } + } + if ( element.isAnnotationPresent( ManyToOne.class ) || element.isAnnotationPresent( OneToOne.class ) ) { mappings.addToOneAndIdProperty( entity, propertyAnnotatedElement ); } @@ -2622,6 +2649,31 @@ public final class AnnotationBinder { column.setUpdatable( false ); } } + + //Make sure that JPA1 key-many-to-one columns are read only too + if ( System.getProperty( "hibernate.enable_specj_proprietary_syntax" ) != null ) { + String columnName = ""; + for ( XProperty prop : inferredData.getDeclaringClass() + .getDeclaredProperties( AccessType.FIELD.getType() ) ) { + if ( prop.isAnnotationPresent( Id.class ) && prop.isAnnotationPresent( Column.class ) ) { + columnName = prop.getAnnotation( Column.class ).name(); + } + + final JoinColumn joinColumn = prop.getAnnotation( JoinColumn.class ); + if ( prop.isAnnotationPresent( ManyToOne.class ) && joinColumn != null + && !joinColumn.name().isEmpty() + && joinColumn.name().equals( columnName ) + && !prop.isAnnotationPresent( MapsId.class ) ) + + { + for ( Ejb3JoinColumn column : columns ) { + column.setInsertable( false ); + column.setUpdatable( false ); + } + } + } + + } value.setTypeName( inferredData.getClassOrElementName() ); final String propertyName = inferredData.getPropertyName(); value.setTypeUsingReflection( propertyHolder.getClassName(), propertyName ); diff --git a/core/src/main/java/org/hibernate/cfg/Configuration.java b/core/src/main/java/org/hibernate/cfg/Configuration.java index a5d378e1bf..e0b6202fe2 100644 --- a/core/src/main/java/org/hibernate/cfg/Configuration.java +++ b/core/src/main/java/org/hibernate/cfg/Configuration.java @@ -3594,6 +3594,15 @@ public class Configuration implements Serializable { } map.put( property.getProperty().getAnnotation( MapsId.class ).value(), property ); } + + public void addPropertyAnnotatedWithMapsIdSpecj(XClass entityType, PropertyData property, String mapsIdValue) { + Map map = propertiesAnnotatedWithMapsId.get( entityType ); + if ( map == null ) { + map = new HashMap(); + propertiesAnnotatedWithMapsId.put( entityType, map ); + } + map.put( mapsIdValue, property ); + } public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String propertyName) { final Map map = propertiesAnnotatedWithIdAndToOne.get( entityType ); diff --git a/core/src/main/java/org/hibernate/cfg/Mappings.java b/core/src/main/java/org/hibernate/cfg/Mappings.java index 13c59797e5..adf465c60c 100644 --- a/core/src/main/java/org/hibernate/cfg/Mappings.java +++ b/core/src/main/java/org/hibernate/cfg/Mappings.java @@ -733,6 +733,8 @@ public interface Mappings { public void addPropertyAnnotatedWithMapsId(XClass entityType, PropertyData property); + public void addPropertyAnnotatedWithMapsIdSpecj(XClass entityType, PropertyData property, String mapsIdValue); + /** * Should we use the new generator strategy mappings. This is controlled by the * {@link Configuration#USE_NEW_ID_GENERATOR_MAPPINGS} setting. @@ -748,7 +750,4 @@ public interface Mappings { public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String propertyName); void addToOneAndIdProperty(XClass entity, PropertyData property); - - - -} \ No newline at end of file +} diff --git a/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/Customer.java b/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/Customer.java new file mode 100644 index 0000000000..bf1285d4cb --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/Customer.java @@ -0,0 +1,243 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat, Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Version; + +@SuppressWarnings("serial") +@NamedQueries({ + @NamedQuery(name = Customer.QUERY_ALL, + query = "select a from Customer a"), + @NamedQuery(name = Customer.QUERY_COUNT, + query = "select COUNT(a) from Customer a"), + @NamedQuery(name = Customer.QUERY_BY_CREDIT, + query = "SELECT c.id FROM Customer c WHERE c.creditLimit > :limit") +}) +@Entity +@Table(name = "O_CUSTOMER") +public class Customer implements Serializable { + public static final String QUERY_ALL = "Customer.selectAll"; + public static final String QUERY_COUNT = "Customer.count"; + public static final String QUERY_BY_CREDIT = "Customer.selectByCreditLimit"; + + public static final String BAD_CREDIT = "BC"; + + @Id + @Column(name = "C_ID") + private int id; + + @Column(name = "C_FIRST") + private String firstName; + + @Column(name = "C_LAST") + private String lastName; + + @Column(name = "C_CONTACT") + private String contact; + + @Column(name = "C_CREDIT") + private String credit; + + @Column(name = "C_CREDIT_LIMIT") + private BigDecimal creditLimit; + + @Column(name = "C_SINCE") + @Temporal(TemporalType.DATE) + private Calendar since; + + @Column(name = "C_BALANCE") + private BigDecimal balance; + + @Column(name = "C_YTD_PAYMENT") + private BigDecimal ytdPayment; + + @OneToMany(targetEntity = CustomerInventory.class, + mappedBy = "customer", + cascade = CascadeType.ALL, + fetch = FetchType.EAGER) + private List customerInventories; + + + @Version + @Column(name = "C_VERSION") + private int version; + + protected Customer() { + } + + public Customer(String first, String last, + String contact, String credit, BigDecimal creditLimit, + BigDecimal balance, BigDecimal YtdPayment) { + + this.firstName = first; + this.lastName = last; + this.contact = contact; + this.since = Calendar.getInstance(); + this.credit = credit; + this.creditLimit = creditLimit; + this.balance = balance; + this.ytdPayment = YtdPayment; + } + + public Integer getId() { + return id; + } + + public void setId(Integer customerId) { + this.id = customerId; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getContact() { + return contact; + } + + public void setContact(String contact) { + this.contact = contact; + } + + public String getCredit() { + return credit; + } + + public void setCredit(String credit) { + this.credit = credit; + } + + public BigDecimal getCreditLimit() { + return creditLimit; + } + + public void setCreditLimit(BigDecimal creditLimit) { + this.creditLimit = creditLimit; + } + + public Calendar getSince() { + return since; + } + + public void setSince(Calendar since) { + this.since = since; + } + + public BigDecimal getBalance() { + return balance; + } + + public void setBalance(BigDecimal balance) { + this.balance = balance; + } + + public void changeBalance(BigDecimal change) { + setBalance( balance.add( change ).setScale( 2, BigDecimal.ROUND_DOWN ) ); + } + + public BigDecimal getYtdPayment() { + return ytdPayment; + } + + public void setYtdPayment(BigDecimal ytdPayment) { + this.ytdPayment = ytdPayment; + } + + public List getInventories() { + if ( customerInventories == null ) { + customerInventories = new ArrayList(); + } + return customerInventories; + } + + public CustomerInventory addInventory(Item item, int quantity, + BigDecimal totalValue) { + + CustomerInventory inventory = new CustomerInventory( + this, item, + quantity, totalValue + ); + getInventories().add( inventory ); + return inventory; + } + + public int getVersion() { + return version; + } + + public boolean hasSufficientCredit(BigDecimal amount) { + return !BAD_CREDIT.equals( getCredit() ) + && creditLimit != null + && creditLimit.compareTo( amount ) >= 0; + } + + @Override + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( o == null || getClass() != o.getClass() ) { + return false; + } + return id == ( ( Customer ) o ).id; + } + + @Override + public int hashCode() { + return new Integer( id ).hashCode(); + } + + @Override + public String toString() { + return this.getFirstName() + " " + this.getLastName(); + } +} diff --git a/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/CustomerInventory.java b/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/CustomerInventory.java new file mode 100644 index 0000000000..8ae34b5a63 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/CustomerInventory.java @@ -0,0 +1,150 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat, Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Comparator; +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.IdClass; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.TableGenerator; +import javax.persistence.Version; + +@NamedQueries({ + @NamedQuery(name = "CustomerInventory.selectAll", + query = "select a from CustomerInventory a") +}) +@SuppressWarnings("serial") +@Entity +@Table(name = "O_CUSTINVENTORY") +@IdClass(CustomerInventoryPK.class) +public class CustomerInventory implements Serializable, Comparator { + + @Id + @TableGenerator(name = "inventory", + table = "U_SEQUENCES", + pkColumnName = "S_ID", + valueColumnName = "S_NEXTNUM", + pkColumnValue = "inventory", + allocationSize = 1000) + @GeneratedValue(strategy = GenerationType.TABLE, generator = "inventory") + @Column(name = "CI_ID") + private Integer id; + + @Id + @Column(name = "CI_CUSTOMERID", insertable = false, updatable = false) + private int custId; + + @ManyToOne(cascade = CascadeType.MERGE) + @JoinColumn(name = "CI_CUSTOMERID") + private Customer customer; + + @ManyToOne(cascade = CascadeType.MERGE) + @JoinColumn(name = "CI_ITEMID") + private Item vehicle; + + @Column(name = "CI_VALUE") + private BigDecimal totalCost; + + @Column(name = "CI_QUANTITY") + private int quantity; + + @Version + @Column(name = "CI_VERSION") + private int version; + + protected CustomerInventory() { + } + + CustomerInventory(Customer customer, Item vehicle, int quantity, BigDecimal totalValue) { + this.customer = customer; + this.vehicle = vehicle; + this.quantity = quantity; + this.totalCost = totalValue; + } + + public Item getVehicle() { + return vehicle; + } + + public BigDecimal getTotalCost() { + return totalCost; + } + + public int getQuantity() { + return quantity; + } + + public Integer getId() { + return id; + } + + public Customer getCustomer() { + return customer; + } + + public int getCustId() { + return custId; + } + + public int getVersion() { + return version; + } + + public int compare(CustomerInventory cdb1, CustomerInventory cdb2) { + return cdb1.id.compareTo( cdb2.id ); + } + + @Override + public boolean equals(Object obj) { + if ( obj == this ) { + return true; + } + if ( obj == null || !( obj instanceof CustomerInventory ) ) { + return false; + } + if ( this.id == ( ( CustomerInventory ) obj ).id ) { + return true; + } + if ( this.id != null && ( ( CustomerInventory ) obj ).id == null ) { + return false; + } + if ( this.id == null && ( ( CustomerInventory ) obj ).id != null ) { + return false; + } + + return this.id.equals( ( ( CustomerInventory ) obj ).id ); + } + +} diff --git a/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/CustomerInventoryPK.java b/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/CustomerInventoryPK.java new file mode 100644 index 0000000000..16cbf127d3 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/CustomerInventoryPK.java @@ -0,0 +1,67 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat, Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid; + +import java.io.Serializable; + + +public class CustomerInventoryPK implements Serializable { + + private Integer id; + private int custId; + + public CustomerInventoryPK() { + } + + public CustomerInventoryPK(Integer id, int custId) { + this.id = id; + this.custId = custId; + } + + public boolean equals(Object other) { + if ( other == this ) { + return true; + } + if ( other == null || getClass() != other.getClass() ) { + return false; + } + CustomerInventoryPK cip = ( CustomerInventoryPK ) other; + return ( custId == cip.custId && ( id == cip.id || + ( id != null && id.equals( cip.id ) ) ) ); + } + + public int hashCode() { + return ( id == null ? 0 : id.hashCode() ) ^ custId; + } + + public Integer getId() { + return id; + } + + public int getCustId() { + return custId; + } + + +} diff --git a/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java b/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java new file mode 100644 index 0000000000..47c8dd7383 --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/IdMapManyToOneSpecjTest.java @@ -0,0 +1,128 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat, Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid; + +import java.math.BigDecimal; +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.test.annotations.TestCase; + +/** + * A test. + * + * @author Stale W. Pedersen + */ +public class IdMapManyToOneSpecjTest extends TestCase { + + public IdMapManyToOneSpecjTest() { + System.setProperty( "hibernate.enable_specj_proprietary_syntax", "true" ); + } + + public void testComplexIdClass() { + + Session s = openSession(); + Transaction tx = s.beginTransaction(); + + Customer c1 = new Customer( + "foo", "bar", "contact1", "100", new BigDecimal( 1000 ), new BigDecimal( 1000 ), new BigDecimal( 1000 ) + ); + + s.persist( c1 ); + s.flush(); + s.clear(); + + Item boat = new Item(); + boat.setId( "1" ); + boat.setName( "cruiser" ); + boat.setPrice( new BigDecimal( 500 ) ); + boat.setDescription( "a boat" ); + boat.setCategory( 42 ); + + s.persist( boat ); + + + Item house = new Item(); + house.setId( "2" ); + house.setName( "blada" ); + house.setPrice( new BigDecimal( 5000 ) ); + house.setDescription( "a house" ); + house.setCategory( 74 ); + + s.persist( house ); + s.flush(); + s.clear(); + + c1.addInventory( boat, 10, new BigDecimal( 5000 ) ); + + c1.addInventory( house, 100, new BigDecimal( 50000 ) ); + s.merge( c1 ); + s.flush(); + s.clear(); + + Customer c12 = ( Customer ) s.createQuery( "select c from Customer c" ).uniqueResult(); + +// c12.getBalance(); + List inventory = c12.getInventories(); + + assertEquals( 2, inventory.size() ); + assertEquals( 10, inventory.get( 0 ).getQuantity() ); + + + Item house2 = new Item(); + house2.setId( "3" ); + house2.setName( "blada" ); + house2.setPrice( new BigDecimal( 5000 ) ); + house2.setDescription( "a house" ); + house2.setCategory( 74 ); + + s.persist( house2 ); + s.flush(); + s.clear(); + + c12.addInventory( house2, 200, new BigDecimal( 500000 ) ); + s.merge( c12 ); + + s.flush(); + s.clear(); + + Customer c13 = ( Customer ) s.createQuery( "select c from Customer c where c.id = " + c12.getId() ) + .uniqueResult(); + assertEquals( 3, c13.getInventories().size() ); + + tx.rollback(); + s.close(); + } + + protected Class[] getAnnotatedClasses() { + return new Class[] { + Customer.class, + CustomerInventory.class, + CustomerInventoryPK.class, + Item.class + + }; + } +} diff --git a/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/Item.java b/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/Item.java new file mode 100644 index 0000000000..d9c2cb87ea --- /dev/null +++ b/testsuite/src/test/java/org/hibernate/test/annotations/derivedidentities/e1/b/specjmapid/Item.java @@ -0,0 +1,144 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat, Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.test.annotations.derivedidentities.e1.b.specjmapid; + +import java.io.Serializable; +import java.math.BigDecimal; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Version; + + +@NamedQueries({ + @NamedQuery(name = "Item.findByCategory", + query = "SELECT i FROM Item i WHERE i.category=:category ORDER BY i.id") +}) +@SuppressWarnings("serial") +@Entity +@Table(name = "O_ITEM") +public class Item implements Serializable { + + public static final String QUERY_BY_CATEGORY = "Item.findByCategory"; + + @Id + @Column(name = "I_ID") + private String id; + + @Column(name = "I_NAME") + private String name; + + @Column(name = "I_PRICE") + private BigDecimal price; + + @Column(name = "I_DESC") + private String description; + + @Column(name = "I_DISCOUNT") + private BigDecimal discount; + + @Column(name = "I_CATEGORY") + private int category; + + @Version + @Column(name = "I_VERSION") + int version; + + public String getId() { + return id; + } + + public void setId(String i) { + id = i; + } + + public int getCategory() { + return category; + } + + public void setCategory(int category) { + this.category = category; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public BigDecimal getDiscount() { + return discount; + } + + public void setDiscount(BigDecimal discount) { + if ( discount.doubleValue() < 0 || discount.doubleValue() > 100.0 ) { + throw new IllegalArgumentException( + this + " discount " + discount + + " is invalid. Must be between 0.0 and 100.0" + ); + } + this.discount = discount; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public BigDecimal getPrice() { + return price; + } + + public void setPrice(BigDecimal price) { + this.price = price; + } + + public int getVersion() { + return version; + } + + @Override + public boolean equals(Object other) { + if ( other == null || other.getClass() != this.getClass() ) { + return false; + } + if ( other == this ) { + return true; + } + return id.equals( ( ( Item ) other ).id ); + } + + @Override + public int hashCode() { + return id.hashCode(); + } +}