On a couple of occasions now, as a result of copy-paste, I have created two JPA entities with the same table name. i.e.:
#Table(name = "myfirsttable")
public class MyFirstTable { #Id #Column private Long id; }
#Table(name = "myfirsttable")
public class MySecondTable { #Id #Column private Integer id; }
I'm using Spring Test, which means that fortunately at least one test fails when I do this. The trouble is that the failures I see will complain about data types. For example, in the above, I would see an exception raised from HibernateJpaAutoConfiguration.class such as expected int but found bigint for myfirsttable. If I look at the class which is supposed to be myfirsttable, I get confused (I'm easily confused), thinking "But it says it's a Long, so surely bigint is the correct mapping?" It can take me a while to work out why I'm seeing that particular message. Similarly, the stack trace may mention being unable to find a field.
So far, there are only a couple of occasions when I have felt the need to create two differing entities pointing at the same table, so as a means of covering the 99% of cases where two entities pointing at the same table is an error, I was wondering whether there is a simple way to set up a test, which would fail in a way that tells me up front that I have created a duplicate table name. I'm thinking about a single test that I can put into all of my projects, which could give me a useful warning identifying this issue.
There are 2 options, that I can see:
You could create a test that will just try and load your ApplicationContext. If that fails something is wrong. Unfortunately to find out what is wrong exactly, you'll have to dig through the logs.
The other option would be to write a test, that will look at all class annotated with #Table and see if more than one have the same table name. I use a similar test in one of my projects to make sure that no entity class uses primitives. There are libriares that make it easier to scan for classes with certain annotations.
Related
I want to find the highest-value id in my entity table. Reading through other posts I found you can construct query methods such as:
public interface ArticleRepository extends CrudRepository<Article, Integer> {
public List<Article> findByOrderByIdDesc();
}
These method gets constructed out of keyword modules, and I saw someone else had made one that returned the top 10 results only. I'd like to find a listing of the base keywords, so I can try to optimize the call (it seems to be running a bit slow). I don't know if it will help, but I'd first like to try something like findFirstByOrderByIdDesc()
the documentation is in Spring Data JPA: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods and I see the FindFirst mentioned here: https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repository-query-keywords
For your needs, how about findFirst5OrderByIdDesc()?
I'm new to Axon Framework. I've a requirement within an asset management module which I am working on.
In this module different types of asset are build, which need to be paired in a similar fashion as one to one relationships in SQL. I am finding it difficult to design an Aggregate for this format.
The business logic validation is as follows:
Two assetIds are inputs. These identifiers resemble aggregate identifiers.
Then, load the asset instances tied to these assetIds and check if the status is unpaired or paired. If both the assets are unpaired then pair them (update the status to paired and add UUID to associatedAssets). Else raise an exception.
I have come up with the following Aggregate class:
#Aggregate
#Data
public class AssetAggregate {
#AggregateIdentifier
private UUID assetId;
private String assetType;
private HashMap<String,String> attributes;
private String status;
private String modifier;
private UUID associatedAsset;
}
My Command Message for pairing is this:
#Data
public class PairAssetCommand {
private UUID assetAId;
private UUID assetBId;
}
In the sample you have given, the PairAssetsCommand can not be handled by a single AssetAggregate as it spans the consistency boundary of two distinct aggregate instances. Namely, two different AssetAggregates.
Note that the Aggregate defines the consistency boundary within your command model. Thus any command taken in by it and all it's resulting events (and following state changes) will be regarded as an atomic operation. Making associations between several entities through this can mean two things:
You create a bigger Aggregate class which spans all AssetAggregates.
You have a External Command Handler (i.e. a #CommandHandler outside of an Aggregate) which handles the PairAssetsCommand.
I'd advise against option one, as it will enlarge the consistency boundary towards the entire set of assets in your system. This will eventually become a major bottleneck the maintain an Aggregate's requirement of "keeping the consistency boundary".
That thus leaves option 2. Let's rephrase the business logic you have defined:
if both the assets are unpaired then pair them(update the status to paired and add UUID to associatedAssets) else raise an exception
This means you cannot validate on a single instance, but need to do this on several. Again, you can take two routes to solving this:
Dispatch a AssociateWithAssetCommand to both the AssetAggregates and dispatch a compensating command if one of the AssetAggregates is already associated.
Use set based validation in the external command handler handling the PairAssetsCommand to validate your business logic.
Which of the two is best is left to preference I'd say. Solution two requires you to have a small query model containing a set of assets and their association status'. Added, this query model needs to be updated in the same transaction as when the association commands occur. Thus, somewhat more complicated.
Hence solution one would be the simplest way to go in your scenario.
I have a situation where I have to make a choice between two options and it's not clear for me what is the difference between that options. I will be very thankful if somebody could explain to me which one should I choose and why.
Long story short I have a simple JPA entity (Kotlin language):
#Entity
#Table(name = "account")
data class AccountEntity(
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long,
var balance: Int,
#ManyToOne
var accountType: AccountTypeEntity
)
And in business-logic layer I want to have a method for updating account balance by its accountId. Basically I need to load account entity by id, then set new balance and lastly use save method which is provided by Hibernate. But I also found the fact that I don't need to call save method in explicit form if my method will be annotated with #transactional. So from that point I have two options
First one
fun updateAccountBalance(id: Long, balance: Int) {
val account = accountRepository.findById(id).orElseThrow { RuntimeException("No account with id=$id found") }
account.balance = balance
accountRepository.save(account)
}
Second one
#Transactional
fun updateAccountBalance(id: Long, balance: Int) {
val account = accountRepository.findById(id).orElseThrow { RuntimeException("No account with id=$id found") }
account.balance = balance
}
Firstly, for me it's not clear what will be the difference of those options in terms of database. Could you please clarify it?
Secondly, I think that in such method I don't really need TRANSACTION (in terms of database) at all because I make only one 'write' operation and for me it looks redundant to use to avoid calling hibernate save method in explicit form. But may be I'm wrong and there are some reasons to use transaction even here. So please correct me.
The difference is almost none in this case. The first example also creates a transaction as it will be created by the save() call when there is no running transaction to adopt. It will live for as long as the save() call. In the second example you create a transaction yourself, which will basically live for just as long as the method invocation. Since there is almost no logic in these methods their footprint will be mostly identical.
This is not a great example to try and figure this out as it is too simplistic. Things will get more interesting when you perform more complicated updates to the entity which may touch multiple tables and records and the same time, especially when you start to do changes which will cause cascaded persists, updates and deletes to happen when you modify a OneToMany collection.
Imagine a system which processes orders. orders have orderlines. And orders are tied to invoices. And orderlines are tied to invoicelines. And maybe orders have parent orders because they're grouped together. And payments are split in bookings and bookinglines which are tied to the orders, orderlines, invoices and invoicelines. Imagine what such an entity hierarchy does in a single save() statement.
In such cases it is all the more clear why a function such as save() still creates a transaction; that one save() call can still represent anywhere between one and thousands of statements being executed depending on the complexity of the entity hierarchy. Having the possibility to rollback all changes in case of a failure is a must.
When you start to work with such an entity structure, you will likely gravitate to using a #Transactional setup quite quickly as you will be running into the infamous lazy initialization error sooner or later.
I have a review table for courses which is made up of multiple objects for different courses.A student should review the courses he is enrolled in every month.The Math,Science,History are tables by themselves but I store foreign keys in the Review table so that each review for the courses is associated with the respective table.
NOTE:a student can only be enrolled in two courses
#Entity
class Review{
//multiple time fields here here
#OneToOne(cascade=CascadeType.ALL,optional=true)
#JoinColumn(name="math_review_id")
Math m;
#OneToOne(cascade=CascadeType.ALL,optional=true)
#JoinColumn(name="science_review_id")
Science s;
#OneToOne(cascade=CascadeType.ALL,optional=true)
#JoinColumn(name="history_review_id")
History h;
}
Super Class
#MappedSuperclass
class Course {
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
#Column(name="id")
int id;
#ManyToOne(fetch = FetchType.LAZY,
cascade = { CascadeType.DETACH,
CascadeType.MERGE,
CascadeType.PERSIST,
CascadeType.REFRESH },
)
#JoinColumn(name = "student_id")
private Student student;
}
Subclass History
#Entity
class History extends Course{
//fields specific to history course
}
Subclass Math
#Entity
class Math extends Course{
//fields specific to math course
}
Student class
#Entity
class Student{
//fields name,id,...
#OneToMany(mappedBy = "student",
cascade = CascadeType.ALL,
fetch = FetchType.LAZY)
private List<Review> reviewsList;
}
I check what courses the student is enrolled in and initialize the Math,Science,History accordingly.I pass a Review object to my reviews.jsp and save the returned #ModelAttribute using hibernate.I dont initialize the courses the student is not enrolled in.I thought uninitialized objects wont be saved but hibernate makes null entries even if not initialized ( I think because they are mapped to a table and are inside a persistent class). I need help how to dynamically construct Review object just with the courses the student is enrolled in.My current design might have flows,any better design suggestions are much appreciated(I have minimal experience in Java and hibernate)
As a suggestion I think you should be weary of creating a class per course. Would it not be sufficient to have a Course class which has a member of type, which could be Math, Science or History. Even that type could itself be an entity: CourseType, which you could have entries for so in your code there would be no Math, Science or History. Instead those are in a database, instead of code.
The Review object would only then interact with a Course. Just think of also all the work you will need to do when you add another course. You will have to update many different files and even add a table in your database, I don't believe you should need to do that.
I imagine you may have some differences between Course classes, and it may be a bit awkward having all these in one class. But from my experience this is typically worth doing, as it drastically reduces the amount of code and allows for more courses to be added without code.
Edit I still strongly recommend you consider reevaluating your decision of 1 class per a course, but anyway your decision. It's really unclear what this Review object is. You say that there are only 2 courses a student will be enrolled in so I imagine that 2 of these fields are null, then. But then it confuses me because you have one class per course, but you have an overeaching review object across all subjects. I would have expected to see:
class EnrolementReview{
Course courseA;
Course courseB;
}
Otherwise if your review depends on fields in your Math, or Science courses, I would expect to have a review class for each course:
class MathReview {
MathCourse course;
}
Or you might have a generic base class for review
abstract class CourseReview<C extends Course> {
C course;
}
if you had common functionality between them. And then an SemesterReview class for reviewing 2 classes in a semester:
class SemesterReview{
CourseReview review1;
CourseReview review2;
}
As far as dynamic composition, IMO I don't think it makes much sense in a statically typed language this notion. You have builder patterns and cake patterns and the like. Some programming languages have some nice stuff in this area like Scala traits but the benefits are very limited, nothing you couldn't do in Java wait a couple of class casts which are a bit evil but it gets the job done.
For all the many permutations of design patterns and methods available to you as a developer, I think it's a bit easier to look at some of the outputs of your design decision, such as:
How many classes am I going to write?
Will I be able to add more courses without writing code and changing
the database tables?
Can somebody else understand my code?
Last Edit
In regards to many null field being a concern, you have some options. Either you have null fields (which you seem to not like), or you do something like encapsulate variable types as an entity (for example each course has a list of Strings, Integers, Doubles etc), which I've seen used quite a bit in many different situations. That works out ok but you do delay some areas which may have been at compile to run-time, as you may need an integer which has a variable name of scienceCategory etc. It also can be awkward if you have some structured data. In general that approach is only good if you really don't know how a client is going to use your system and so you expose more of it to them to use.
However my personal favourite, is to follow the natural composition of your class, and encapsulate families of variables into their own class, which you expect wont always be applicable, as in if one isn't applicable all the others wont be either. The logic whether these classes are present should be very explicit however, either they should be Optional<ScienceInformation> or you should have some methods somewhere which returns a boolean whether or not this option should exist or not. Then operations can be performed on those options in the system you create. Just need to be careful you don't create objects which are too deeply nested as in objects which are made up of objects, which are made up of objects, (not always a problem but usually it is).
But really I don't think it's super important what way you choose, none of them will give you the comfy feeling that writing a class gives you. Just need to think about how you are going to abstract over these entities (eg. Course) in a way which will not lead you to an un-maintainable mess. You clearly have a very complete knowledge of your domain but you should write your code in a way where I (somebody who doesn't know about how many courses are in a semester) can read the code and then find that out without reading comments (that would be cheating), what the answer to that question is.
Let's say, i have an User and a Product.
The user should be able to rate products and a rating can have a lot of properties like for example a number of stars from 1 to 5.
I'd like to have the Product and the User in different Maven modules.
However, Product should know its Owner, so there is a dependency to the module, holding User.
I also would like to have a Rating-Module that contains everything related to ratings.
I constructed the Rating
#RelationshipEntity(type="RATES")
public class Rating{
private Long id;
#StartNode
private User rater;
#EndNode
private Product ratee;
#Property
private RatingProperty property;
//Getter/Setter
}
Where the RatingProperty contains the int representing the 1 to 5 star rating.
Now I understand from the Documentation that I need to have the Rating as an attribute inside some node because SDN4 doesn't accept it otherwise.
Indeed when i did not use it as an attribute and tried save it, i got the id null and not element appeared in the DB.
Since the Rating needs to know both User and Product, I get a cyclic dependency when I try to put the Rating into the User class.
The same when i put it into the Product Class.
As far as I understand at the moment, using a RelationshipEntity seems to not be possible when the Start- and EndNode entities are in different Maven Modules, because the Relationship needs to know both and one of the nodes needs to know the relationship.
This doesn't seem right, so I think I understand something very wrong.
I also tried creating a new NodeEntity inside the Rating-Module just to hold the Rating. This was
#NodeEntity
public class RatingWrapper{
private Long id;
#Relationship(type="RATES)
private Rating rating;
//Getter/Setter
}
but this way i got the same behavior that i did when i didn't use the RelationshipEntity as an attribute somewhere.
Do you see a way to do this better?
A RelationshipEntity represents an edge with in the graph on which you can set and retrieve properties via your domain objects. However, because Neo4j does not support hyper-edges (edges attached to other edges), those properties must be simple Java properties, not other objects in your domain like RatingProperty.
Try replacing RatingProperty with a simple Integer first and see if that solves your problem. If so, you can then use a Custom Converter to convert between the Integer property rating in the graph and your RatingProperty object.
If your domain objects are in different modules this should not cause any problems: just ensure that all of the relevant packages are enumerated in the argument to the SessionFactory constructor:
new SessionFactory("app.module1.domain", "app.module2.domain", ...)
When testing Vinces advice, I changed the progress of creating the relationship. Unitl now, i persisted the startnode, then the endnode and then tried to use a repository extends GraphRepository<Rating> to save the RelationshipEntity. Whenever I did this, i got a rating with id null. When I added the rating as an attribute to the startnode and instead of saving the new relationship, saved the startnode, it worked.
I'm not sure, if this is the proposed way, but I got my relationship, so it works for me.