I am a newbie to Hibernate and trying to do something like this:
I have 2 tables.
One is Visitor and another is Visited_Page.
The Visitor table has a structure:
{
visitor_id *int*,
visitor_username *varchar*,
visito_name *varchar*
}
The Visited_Page table structure is:
{
vipage_id *int*,
vipage_url *varchar*
}
And many to many mapped table structure is like:
visitor_id int, vipage_id int.
When the User hits a URL in my website, a new entry should get created in the mapped table with the structure as mentioned above.
I have completed this part using hibernate with annotations in Java.
Now I have to add another column Timestamp in the mapped table. I am not able to find how to do it. Please help.
Create a class say VistorVisitedPage
#Entity
#Table(name = "Vistor_Visited_Page")
#AssociationOverrides({
public class VistorVisitedPage {
private Date createdDate;
private String createdBy;
}
Also refer this for complete information.
Related
I start a project with spring boot, I use a database with 6 tables.
It is a CRUD application .
So , I have my entities/dto/service/controller/repository packages for 5 tables. (6 tables in SQL)
Now, I would like to update a row on the column of table x(SQL) of entity x to another entity y at a specific row.
In my opinion, it should be done at the service layer at create X, but how?
Should I create a xyDTO with data from 2 entities? I am afraid of doing it , the table y it doesn't update automatically.But when create the xyDTO. I don't want this.
How I can update the data of specific DTO x to another DTO y (6th table of SQL), at the same time
I cannot find similar example online. Could anyone help me?
My code:
#Entity
#Table(name = "repo")
public class Repo {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
Long id;
#Column(name="stock")
private Long stock;
}
#Entity
#Table(name = "voucher")
public class Voucher {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private Long id;
#Column(name = "quantity")
private BigDecimal quantity;
#Column(name = "type")
private boolean type;
}
#Service
public class VoucherService{
#Override
public Voucher dtoToEntity(VoucherDTO dto) {
Voucher voucher = new Voucher();
voucher.setId(dto.getId());
voucher.setDescription(dto.getDescription());
List<VoucherProduct> voucherList = new ArrayList<>();
for (VoucherProductDTOMini inv : dto.getVoucherproducts()) {
VoucherProduct voucherL = voucherProductService.DTOtoEntity(inv);
voucherList.add(voucherL);
}
voucher.setVoucherproducts(voucherList);
return voucher;
}
#Override
public VoucherDTO createVoucher(VoucherDTO voucherDTO) {
Voucher voucher=new Voucher();
voucher=voucherRepository.save(voucher);
VoucherDTO voucherDTOnew=new VoucherDTO(voucher);
return voucherDTOnew;
}
}
I should
check the type of my voucher (true), and I should add on my repo entity at
stock.
In which way can I update the two entities at the same time?
When I add a true voucher, I should add on my repo.stock the data of voucher.quantity.
First, I would like to highlight a few things in your code:
I cannot find the reason to use #Override annotation on those methods in your Service.
In createVoucher method you create completely empty entity, this is not a good thing to do.
DTO stands for Data Transfer Object, and usually in Spring applications it is used to transfer data to or from the service. For example: Controllers. When user makes a Http Request to receive all Vouchers for example, you would like to return VoucherDto with only those fields that you want users to see.
You can have different DTO objects for Getting entity values and Updating them. Because sometimes you want to allow users to update only certain properties.
To answer your question on how to update two entities in a single call. As I understood your question, you want to update different properties in two different entities via a single request. This is possible, though there are different approaches to this.
Create two different DTOs, one for each entity. Create two different Http Requests each would take one DTO and call a method in a service to update each Entity. ex.: VoucherController.updateVoucher -> VoucherService.updateVoucher and RepoController.updateRepo -> RepoService.updateRepo. I personally prefer this as a solution because your entities Voucher and Repo don't have any relation.
Create a single DTO object, containing all fields required to be updated, then in the service method find your Voucher, and Repo and update their fields, then save both entities. This would be a messy approach when you have many entities.
There would be another different approach if you would have a relation between your Repo and Voucher entities, for example a OneToMany.
Let me know whether this answers your question. There is nothing wrong to have many DTO objects and Services, etc.
If you would like to easily generate all the DTO objects, have a look at this: https://github.com/OpenAPITools/openapi-generator
I have 2 models, a workout and an exercise as follows:
#Entity
public class Workout extends Model {
#Id
public Integer id;
#ManyToMany(cascade = CascadeType.REMOVE)
public List<Exercises> exercises;
}
#Entity
public class Exercise extends Model {
#Id
public Integer id;
#ManyToMany
public Workout workout;
}
When I load a workout and attempt to display it, I want the exercises to be displayed in the order that the relationship (between the workout and exercise) was created. However, the exercises are instead displayed in the order that the exercises were created. Here's a sample of the display (in case it helps):
<ul>
#workout.exercises.map { exercise =>
<li>
#exercise.name
</li>
}
</ul>
Any ideas on how I can achieve this? I've tried adding #OrderBy to the property definition, but this doesn't allow me to order by the relationship table fields, which would be ideal (with the addition of a created_date field on that table, as well).
Much appreciated!
There is no easy way as far as I can tell. Just create a getSortedExcercises() which returns the list sorted to use in the templates:
public List<Exercises> getSortedExcercises() {
List<Exercises> l = new ArrayList(this. exercises);
Collections.sort(l, new ExercisesComparator());
return l;
}
In terms of SQL you need an order by clause to guarantee the order of the returned rows. That is the behaviour you are seeing of '... displayed in the order that the exercises were created.' ... is actual specific to your DB's convention (and not portable across DB's).
If you want SQL result ordering by 'order that the relationship (between the workout and exercise) was created' ... then what that strictly means is that you need a db column to store that on the intersection table and have the SQL order by that column.
Now, with #ManyToMany by default the generated intersection table does not have a 'When Created' column. You can either model the intersection table explicitly (change from #ManyToMany to use 2 #OneToMany etc) or manually define your intersection table with a 'When Created' column and DB triggers to populate that ... and then reference that db column in an order by clause.
I'm using toplink JPA in a webapp and I want to map just one table to a class hierarchy. I want to have one class that represents most of the data, and one class that inherits from that (so it gets all the fields of the superclass, plus a couple of other that hold large amounts of data). I don't want the large amounts of data all the time, don't want to hold them in request objects etc. I only want the large bits when someone has selected one of the summaries. I've setup the classes as follows (simplified as an example).
#Entity
#Table(name = "TRANSCRIPTS")
#MappedSuperclass //also tried without this - same error
public class Summary {
#Id
#Column(name = "id")
private long id;
#Column(name = "title")
private String title;
//rest of class etc.
}
#Entity
#Table(name = "TRANSCRIPTS")
public class Detail extends Summary {
#Id
#Column(name = "fullText")
private String fullText;
//rest of class etc.
}
When I try and get data using this hierarchy, I get an error along the lines of
Unknown column 'DTYPE'
So it's looking for a descriminator column. Which I haven't setup, because it's not that sort of relationship.
Is there a different way I can map this summary/detail relationship in JPA? Or should I give up on the class inheritance and have two separate unrelated classes, one representing summary data and one representing the full data (and redefining the summary fields).
Thanks.
DTYPE it is discriminator column that Toplink tries to access to choose between your entities,
If you add that column to your table schema, it will start working.
DTYPE is INTEGER typed column in database.
You could specify your own discriminator column using following code snippet:
#Entity
#DiscriminatorColumn(name="type",discriminatorType=DiscriminatorType.INTEGER)
#DiscriminatorValue("1")
class TestClass {}
Here is some documentation for you http://www.oracle.com/technetwork/middleware/ias/toplink-jpa-annotations-096251.html#CHDJHIAG
Is there a way I can map a field in an hibernate object to be loaded with a table query?
As an example lets say Table_Message has fields id(int),message_key(varchar),message_content(Clob),language(varchar). This table will hold messages in different languages(locale).
And another table thats mapped to an entity using hibernate. Comments with fields id(int),comment_message_id(varchar),created_date(datetime). comment_message_id refers to Table_Message's message_key column.
EDIT: Table_Message is NOT a mapped Entity in hibernate
Assuming my comment class is
public class Comment
{
int id;
String message;
Date createdDate;
}
Is there a way to tell hibernate to load message by joining Comment table and Table_Message table by message_key with a default locale (for example 'en').
Basically is there a way to tell hibernate to load a field by running a specific query? And if so what is that way?
I know about writing a Custom SQL query for loading the entity. But since I'm using XDoclet there doesn't seem to be a way to do that. Also it will be very convenient if there's a way to do that for a single field.
I guess ResultTransformer may help you in this. Please check
http://docs.jboss.org/hibernate/orm/3.3/api/org/hibernate/transform/ResultTransformer.html
http://stackoverflow.com/questions/6423948/resulttransformer-in-hibernate-return-null
You must join the tables by comment_message_id with message_key and further filter the result by language. I assume the message_key is unique.
As a side notice: you should use integer keys to have better performance.
You can try to write a database view in SQL and create an entity to opaque the view:
CREATE VIEW Comment_Table_Message AS
SELECT c.id, c.comment_message_id, c.created_date, m.id AS mid,
m.message_content, m.language
FROM Comment c, Table_Message m
WHERE c.comment_message_id = t.message_key;
Now you can create an entity CommentTableMessage and use JPQL to filter results by language:
SELECT x FROM CommentTableMessage x WHERE x.language=?1
If Table_Message was a Hibernate entity you would write (in JPA terms):
#Entity
public class Comment
{
int id;
#ManyToOne()
#JoinColumn(name="comment_message_id")
TableMessage tableMessage;
String message;
Date createdDate;
}
#Entity
public class TableMessage {
int id;
#Id
String messageKey;
bytes[] messageContent; //I don't know how you want to deal with Blobs?
String language;
}
Having that you can write a simple JPA Query: (Can you use JPA ? - next assumption)
SELECT c FROM Comment c WHERE c.tableMessage.language=?1
I have a Person entity mapped by Hibernate to a database table in a database catalog "Active". After a period of time, records in this database table in the "Active" catalog are archived/moved to an exact copy of the table in a database Catalog "History". I have the need to retrieve from both the Active and History Catalogs. Is there a better way to model this with Hibernate annotations than making an abstract class that 2 classes extend from.
This is what I have now.
#MappedSuperclass
public abstract class Person {
#Id
private Integer id;
private String name;
}
#Entity
#Table(name="Person", catalog="Active")
public class PersonActive extends Person {
}
#Entity
#Table(name="Person", catalog="History")
public class PersonHistory extends Person {
}
To my knowledge, that would be the right way to do it with annotations (you kinda have two tables so you need two entities). Then run a polymorphic query on the Person entity. I find this pretty clean by the way.
PS: Can you add a pointer on how to do this with mapping files, I'm really curious.
My thought would be to write a query to select both tables from db A and B. then create a query with hibernate and map it to your class.
example:
#Entity
#NamedNativeQuery(
name="GetAllPerson",
query="select * from A.Person inner join B.Person on A.Person.Id = B.Person.Id"
)
public class Person {
...
}
Not sure if it could work, your question made me also curious about the best way to do it :). I'll test it tonight after work and see if its any good.
I think there is a subproject of hibernate named shards. It is designed to work with multiple relational databases. If you want to use it, you may need big changes in your code.