I have problems in mapping custom collection with JPA (Hiberante provider). For example when I am using object with attribute
List<Match> matches;
with
<one-to-many name="matches">
<cascade>
<cascade-all />
</cascade>
</one-to-many>
in my ORM file, it is allright; But if I replace "List matches;" by
private Matches matches;
,where "Matches" is defined like:
public class Matches extends ArrayList<Match> {
private static final long serialVersionUID = 1L;
}
It produces following error:
Caused by: org.hibernate.AnnotationException: Illegal attempt to map a non collection as a #OneToMany, #ManyToMany or #CollectionOfElements: by.sokol.labs.jpa.MatchBox.matches
Thanks for your attention!
You can, but you have to refer to it as one of the common collections - List or Set.
so:
private List matches = new Matches();
Why? Because Hibernate makes proxies to your collections to enable lazy loading, for example. So it creates PersistentList, PersistentSet and PersistentBag, which are List but aren't Matches. So, if you want to add additional methods to that collection - well, you can't.
Check this article for more details.
You have a solution, however. Don't use inheritance, use composition. You can, for example, add a method to your entity called getMatchesCollection() (in addition to the traditional getter), which looks like:
public Matches getMatchesCollection() {
return new Matches(matches);
}
And your Matches class would look like (using google-collections' ForwardingList):
public class Matches extends ForwardingList {
private List<Match> matches;
public Matches(List<Match> matches) { this.matches = matches; }
public List<Match> delegate() { return matches; }
// define your additional methods
}
If you can't use google collections, simply define the ForwardingList yourself - it's calling all the methods of the underlying List
If you don't need any additional methods to operate on the structure, then don't define a custom collection.
Hibernate requires persistent collection-valued fields to be declared as an interface type (because they will be replaced with Hibernate's implementation for lazy loading purposes). From the reference documentation:
6.1. Persistent collections
Hibernate requires that persistent collection-valued fields be declared as an interface type. For example:
public class Product {
private String serialNumber;
private Set parts = new HashSet();
public Set getParts() { return parts; }
void setParts(Set parts) { this.parts = parts; }
public String getSerialNumber() { return serialNumber; }
void setSerialNumber(String sn) { serialNumber = sn; }
}
The actual interface might be
java.util.Set, java.util.Collection,
java.util.List, java.util.Map,
java.util.SortedSet,
java.util.SortedMap or anything you
like ("anything you like" means you
will have to write an implementation
of
org.hibernate.usertype.UserCollectionType.)
Notice how the instance variable was
initialized with an instance of
HashSet. This is the best way to
initialize collection valued
properties of newly instantiated
(non-persistent) instances. When you
make the instance persistent, by
calling persist() for example,
Hibernate will actually replace the
HashSet with an instance of
Hibernate's own implementation of Set.
So your second approach is not possible, at least not the way you declared it. But to be honest, I don't really see the point.
Related
I'm trying to define a container for a whole bunch of classes as some parts of the code will make more sense with a collection but other places will make sense with single values.
Ideally I'd like to do this:
public class AllModes<T> {
private T<Car> car;
private T<Boat> boat;
private T<Train> train;
private T<Plane> plane;
...40 more of these...
}
then I'd like to use the class like:
AllModes<List> allModes;
AllModes<Optional> oneOfEachMode;
But I get the error I get is "The type T is not generic; it cannot be parameterized with arguments "
The reason I'm defining these in multiple variables and not a single HashSet based on a superclass is I want to have get methods that return the correct types to avoid consumers of this class needing to cast down everywhere as each object has its own distinct fields.
I also considered just storing a single value list or set but I thought it might less error prone to use the correct type I intended (ie. one value)
You can't achieve what you want using the Java type system.
Since you can't have a generic container type, you'll need to enforce the invariants with dedicated constructors (or subclasses).
But if you do so, the clients of your class will not be able to distinguish between different container types (Optional vs List), they will need to work with a generic abstraction (like Stream, Iterator, Iterable, whatever suits you).
Here's an example:
public class AllModes {
private final Supplier<Stream<Car>> cars;
private final Supplier<Stream<Boat>> boats;
public AllModes(Optional<Car> car, Optional<Boat> boat) {
// Assuming Java 8, when Optional did not have a stream() method yet
this.cars = () -> car.map(Stream::of).orElse(Stream.empty());
this.boats = () -> boat.map(Stream::of).orElse(Stream.empty());
}
public AllModes(List<Car> cars, List<Boat> boats) {
this.cars = cars::stream;
this.boats = boats::stream;
}
public Stream<Car> getCars() {
return cars.get();
}
public Stream<Boat> getBoats() {
return boats.get();
}
}
You can't solve it this way. Use the instanceof operator instead. Here is an example:
public class AllModes<T> {
private T object;
private void check(T object) {
if(object instanceof Boat){
System.out.println("Boat");
// your code for Boat goes here
} else if (object instanceof Car) {
System.out.println("Car");
// your code for Car goes here
}
}
}
I'd suggest you take a step back and re-consider what exactly you want to achieve with this container. E.g. ask yourself what its domain is or what the client is supposed to do with Allmodes<T>...
Another more concrete question that comes to mind is how exactly you intend to popuplate that Optional<T> generically? Will it be the first element in the List<T> or the last? Or an element which satisfies a specific Predicate<T>?
Your design doesn't seem to be that well thought out yet.
What you could do which would come close to what you descibed (in case I got that right) is provide an accessor of type Stream<T> as you could get both a List<T> aswell as an Optional<T> from it. Your client would then have to make that decision and also determine how exactly to derive the Optional<T> from the Stream<T>.
From The Java™ Tutorials - Why Use Generics?:
By using generics, programmers can implement generic algorithms that work on collections of different types, can be customized, and are type safe and easier to read.
You can have multiple types in class and then you can associated them with the fields. But in your case, you have several fields with some type. A class don't have much dependencies on others. You should design you class in a way that there are no much dependencies there.
public class AllModes<T,T1,T2,T3> {
private T car;
private T1 boat;
private T2 train;
private T3 plane;
}
Lets say I have a Namespace class like follows:
abstract class Namespace {
protected prefix;
protected Map<String, String> tags;
public setTag(String tagKey, String tagValue) {
tags.put(tagKey, tagValue);
}
}
I have been told that a good design is to have separate implementations of each namespace with getters defining the information being retrieved from the tags map. ie.
class FooNamespace extends Namespace {
public String getNameTag() {
return tags.get("name");
}
}
We can have separate implementations of a namespace like BarNamespace which will have different tags stored (BarNamespace does not have a name tag for ex. and instead has an age tag). Why does the above design make more sense than simply having the consumer of a simple Namespace class request the tag they want. ie:
class Namespace {
private prefix;
private Map<String, String> tags;
public String getTag(String key) {
return tags.get(key);
}
}
The above is used like
Namespace.getTag("name");
The answer depends a lot on what you wish to achieve - but if I have to type getTag("name") a few hundred times, I'm bound to make a mistake.
getNameTag takes out some of the guess work and reduces the possibility that I'll type "name" wrong without noticing. It also reduces the amount of knowledge I need to have about the API - I know I can get the value for the name tag, but I don't need to know how that is actually implemented - and it might change between implementations.
Is it a "good design" is a matter of opinion and is dependent on how the intended class is to be used. Is "name" common enough in the application to be useful? What about "date" or "numeric" values - some helper methods there might be nice ;)
The one thing that bugs me about this is that while Bar does not have an accessor for "name", its backed by an abstract Namespace class that contains a raw Map so anyone can shove in a "name" tag by doing a Bar.putTag("name", "nameValue"); Any ideas on how to implement the "setters"?
This is also a bug-bear I have to the collections API generally.
You could create a non-mutable and mutable concepts...
public interface Namespace {
public String getTag(String key);
}
public interface MutableNamespace extends Namespace {
public void setTag(String key, String value);
}
Then you can begin to abstract those...
public abstract class AbstractNamespace implements MutableNamespace {
private prefix;
private Map<String, String> tags;
public setTag(String tagKey, String tagValue) {
tags.put(tagKey, tagValue);
}
public String getTag(String key) {
return tags.get(key);
}
}
And finally provide useful implementations for the context that it might be used in...
public interface MySuperHelpfulNamespace extends Namespace {
public String getNameTag();
}
public class DefaultMySuperHelpfulNamespace extends AbstractNamespace implements MySuperHelpfulNamespace {
public String getNameTag() {
return tags.get("name");
}
}
Then write you app to support them...
public void someMethodWhichDoesNotNeedToChangeTheValues(MySuperHelpfulNamespace namespace) {
//...
}
public void someMethodWhichDoesNeedToChangeTheValues(MutableNamespace namespace) {
//...
}
This is essentially an example of "coding to interface (not implementation)
The problem stems from..
Your attempt to reuse Namespace via inheritance for it's property: the Map.
The idea behind object orientation is to..
Tell objects to perform behaviors.
What is an Object?
Hiding internal state and requiring all interaction to be performed through an object's methods is known as data encapsulation — a fundamental principle of object-oriented programming.
When ClassA extends ClassB, the subtype ClassA should inherit the behaviors, or the public interface, of it's supertype ClassB. Your Namespace type doesn't seem to define any behaviors.
You may consider the setter or getter to be behaviors,
But don't be fooled. There is currently no reason for a developer to prefer your Namespace type over just using a Map, other than changing the interface they use from get to getTag.
getter & setter methods violate OOP. Feel free to read up on the discussion.
How should Namespace actually be used? What requirement is it fufilling? What behaviors should Namespace define?
You can answer this by analyzing how the getter is being used. To give an example, maybe you plan to append it to a StringBuilder to conjure some XML.
Imagine your requirement was..
Append an individual tag from a variety of XML tag sets to a StringBuilder that'll be used for rendering.
Instead of doing..
StringBuilder builder = ...;
Namespace namespace = ...;
builder.append(namespace.getTag("name"));
Namespace could be responsible for appending it's tags (Namespace is the owner of the Map storing the tags) to whatever is requesting it.
public final class Namespace {
private final Map<String, String> tags;
public Namespace(Map<String, String> tags) {
this.tags = tags;
}
// if you REALLY need to add tags after instantiation
public Namespace addTag(String key, String value) {
Map<String, String> tags = new HashMap<>(this.tags);
tags.put(key, value);
return new Namespace(tags);
}
// the behavior that fufills the requirement
public void appendTo(StringBuilder builder, String key) {
builder.append(tags.get(key));
}
}
Notice how Namespace has behavior (appends to a StringBuilder) rather than act as a proxy for Map.
StringBuilder builder = ...;
Namespace namespace = ...;
namespace.appendTo(builder, "name");
I'm not looking for reasons to create subtypes (not forcing it). You should only create subtypes when you must extend upon the behavior of the supertype. If BarNamespace doesn't add any functionality to Namespace, there's no need for it.
After creating Namespace to cover the functionality your post exposes, I had no need for subtypes. It seemed as if everything was elegantly handled by Namespace.
You didn't specify your requirements, but hopefully this answer will guide you towards determining them (based on how you're using the getter) and implementing them in an object oriented manner.
As #MadProgrammer pointed out:
if I have to type getTag("name") a few hundred times, I'm bound to make a mistake.
If you find yourself needing to type "name" quite often, then you may wanna include a type-safe way for performing that behavior.
In a situation like this, you could prefer composition over inheritance. Instead of having subtypes extend Namespace, you could create types that reference a Namespace to perform what you want to do.
public final class Bar {
private final Namespace namespace;
public Bar(Namespace namespace) {
this.namespace = namespace;
}
public void appendNameTo(StringBuilder builder) {
namespace.appendTo(builder, "name");
}
}
You may say "Wait! I wanna pass Bar to where a Namespace is expected!"
This would be pointless. If code relies on Namespace, there would be no type safety to be expected, even in your code. For example:
void doSomething(Namespace namespace) {
}
Unless you casted or declares appendNameTo to Namespace, you wouldn't have access to any methods defined in Bar anyways. You said subtypes may have different tags. This means if you're going for type safety, your subtypes would all have different public interfaces, hence why I didn't extend Namespace.
I have a number of classes mapped as an inheritance hierarchy into a single table.
I would like to use the following Criteria query but this results in a ClassCastException since Class cannot be cast to String.
Set<Class> childClasses = new HashSet<>();
childClasses.add(Child1.class);
childClasses.add(Child2.class);
session.createCriteria(Parent.class)
.add(Restrictions.in("class", childClasses)
.list();
I note that Hibernate does support specifying a single class using Restrictions.eq("class", childClass) so I can workaround by using a Disjunction'. I also know that this would work if my resriction was based on the discriminator strings for each subclass but I would prefer not to use these.
It is possible to use Criteria in this manner? The accepted answer to this question suggests that it works when the class is a property of the class you are basing your Criteria on but it doesn't seem to work in the case I've shown above.
Looking at the source code, I would say that this is a Hibernate bug.
For example, SimpleExpression (returned by Restrictions.eq) calls criteriaQuery.getTypedValue which handles conversion of Class value to the corresponding discriminator value.
InExpression (returned by Restrictions.in) adds values as they are, without conversion. That's why you get ClassCastException, because later an attempt to cast Class to String is made (obviously the type of your discriminator value is String).
You could avoid using this form until it's fixed (you already suggested the proper workarounds), or, if you would really like to stick to using Class objects directly, then you could implement custom InExpression in your project. For example, something like:
public class ClassInExpression extends InExpression {
private static final String CLASS = "class";
private final Collection<Class> values;
public ClassInExpression(Collection<Class> values) {
super(CLASS, values.toArray(new Object[values.size()]));
this.values = values;
}
#Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
if (criteriaQuery.getTypeUsingProjection(criteria, CLASS).isComponentType()) {
return super.getTypedValues(criteria, criteriaQuery);
}
return convertToDiscriminatorValues(criteria, criteriaQuery);
}
private TypedValue[] convertToDiscriminatorValues(Criteria criteria, CriteriaQuery criteriaQuery) {
List<TypedValue> resultList = new ArrayList<TypedValue>();
for (Object value : values) {
resultList.add(criteriaQuery.getTypedValue(criteria, CLASS, value));
}
return resultList.toArray(new TypedValue[resultList.size()]);
}
}
Then you would use it instead of Restrictions.in:
session.createCriteria(Parent.class)
.add(new ClassInExpression(childClasses))
.list()
I have following classes
class A {
private Long id
private List<B> listB;
private C c;
...
}
class B {
private Long id
private A a;
private List<D> listD;
...
}
class C {
private Long id
private A a;
...
}
class D {
private Long id
private B b;
...
}
I need a copy of A, include all of it's properties except all id column.
I have 2 solutions:
1. Clone each object and set all of the ids null;
2. Make a constructor like this:
public A (A a){
//copy all properties except id
this.xxx = a.xxx;
...
}
But i need write so much code for this function, any one has some better method to implement this function?
Thanks a lot.
When you are saying Deep cloning of the object particularly the one of type Class A where you have an instance variable of a container type, you have below two widely known ways:
1) You Serialize and Deserialize the object.
2) You traverse through each method and call clone explicitely.
For first implementation, you may mark the id fields as transient and that should solve your purpose.
For second approach, you may override the clone method in each class where you set the id field as 0/-1) and call super.clone()
You can use Mapstruct , it's a powerful mapping library where you can configure all the fields exclusions for your specific class or nested class, without having to write all the getters/setters manually.
I personally use it for deep cloning jpa entities excluding ids or auditable fields.
Ex:
#Mapping(target="id",ignore=true")
EntityA cloneEntityAWithoutId(EntityA origin);
Mapstruct will generate for you the implementations using getters and setters of the EntityA, excluding the id field.
Obviously is a lot configurable, see the documentation I shared above.
//Interface DAO
public abstract class BaseDAO<T extends BaseDTO> {
public void update(T t) throws DBException {
Field[] fieldsToInsert = t.getClass().getDeclaredFields();
//code to update database object academic or event
}
public Integer create(T t) throws DBException {
Field[] fieldsToInsert = t.getClass().getDeclaredFields();
//code to create academic or event in database
}
}
//Concrete DAOs
public class AcademicDAO extends BaseDAO<AcademicDTO> {
//provide implementation
}
public class EventDAO extends BaseDAO<EventDTO> {
//provide implementation
}
//Transfer object
public class AcademicDTO extends BaseDTO {
String title;
String surname;
//getters and setters
}
public class BaseDTO {
protected Integer ID;
public Integer getID() {
return ID;
}
public void setID(Integer ID) {
this.ID = ID;
}
}
Hello Guys, I have a sample code on me that follows the above structure to create a small java application to manage academics and events. It is leniently following this pattern
1- You experts are familiar with this pattern more than me. I would like to understand why generics are used in this case so DAOs can extend and implement a generic base class. It would be great if one can show how generics here may be advantageous using an example.
2 - I have also witnessed the use of java Fields. Is there a link between generics and Fields?
I would like to document DAO pattern in an academic report, but I am finding difficult to understand how Generics and Reflect Field play a part here. Do they support flexibility and loose coupling?
The code you've provided is reusable set of logic to load and persist entities. Many times, in an application of non-trivial size, you'll wind up persisting many different types of objects. In this example, you can define as many objects as necessary, but only define the logic to actually save and load once. By asking the DTO what Field objects are there, it can get at the data to help construct queries for loading and saving.
Generics allow you to use this pattern while maintaining type safety. AcademicDAO can only handle AcadmeicDTO. You can't use AcademicDAO to store EventDTO. Generics allow the instance of the class to rely on a more specific type when dealing with the Field objects. If you didn't have generics, the BaseDAO would take Object, and you wouldn't be able to access any methods except those that Object provides because the JVM wouldn't know what class is provided, so it has to limit it's knowledge to that of Object. Using getClass().getDeclaredFields() bypasses that limitation because getClass() returns the actual class of the Object parameter.
Field is just a way to use reflection to access the values of the properties in each DTO. If you had to access the fields directly, with getTitle(), you couldn't reuse a generic base class to do your persistence. What would happen when you needed to access EventDTO? You would have to provide logic for that. Field allows you to skip that logic.
Edit:
To explain what I mean by accessing getID, you could do the following within BaseDAO because T is known to be a BaseDTO with a getID() method defined:
public abstract class BaseDAO<T extends BaseDTO> {
public boolean update(T t) throws DBException {
Integer id = t.getID();
Field[] fields = t.getClass().getDeclaredFields();
// Assuming you have a db object to execute queries using bind variables:
boolean success = db.execute("UPDATE table SET ... WHERE id = ?", id.intValue());
return success;
}
}
If you had this instead (in a non-generic class):
public boolean update(Object o) throws DBException {
// This line doesn't work, since Object doesn't have a getID() method.
Integer id = t.getID();
Field[] fields = o.getClass().getDeclaredFields();
boolean success = db.execute("UPDATE table SET ... WHERE id = ?", id.intValue());
return success;
}
You'd have to look through those Field objects, or ask for the ID field and assume it existed.
For question 1. The use of generics allows the same implementations of update and create to be used regardless of the type of the DTO. Consider if you didn't use generics. Then the best you could do for the parameter type of update would be BaseDTO, but then you could call
academicDAO.update( eventDTO )
which doesn't make sense. With the code as you have it, this would be a type error. So the main advantage is: better type checking.
For question 2. The use of Fields allows a single implementation of update and create to work on DTO object of various concrete types.