how to mapping hibernate entity to db view - database

Could you help me how can I mapping to any entity to db view?
Scenario is here, We create a view on db with native sql we have to do like this and we want to mapping this view to ours entity.
How can we do that? We try to create an entity with same columns on view but it doesn't work?

Hibernate-specific #Immutable annotation which I use in the following code snippet.
View can be mapped as like below....
#Entity
#Immutable
public class <NAME>View {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id", updatable = false, nullable = false)
private Long id;
#Version
#Column(name = "version")
private int version;
The #Immutable annotation tells Hibernate to ignore all changes on this entity, but you can use it to retrieve data from the database.
List<View> views = em.createQuery("SELECT v FROM View v", View.class).getResultList();

Related

In Entity Framework Core, how can my EF entities return a value from another table that is not an entity as a lookup?

I'm using EF Core 6 on a project. Most of my tables have a field like CreatedBy/UpdatedBy that includes a user id. There are only a few occasions where I need to show the full name associated with the user id, but that value is in another table in a different database, but on the same server.
Is creating a view that joins to the needed table only way to handle this? Could I create function in the database where my EF Core entities are modeled? How would that work code wise?
As EF context does not support cross database queries. Therefore, workaround can be a SQL view.
Is creating a view that joins to the needed table only way to handle this?
Yes you can do that. While creating view you should consider below way:
SELECT {Your 1st Table Column} [YourFirstDatabase].[dbo].[Your1stDbTable] WHERE UserId = (SELECT {Your 2nd Table Column} FROM [YourSecondDatabase].[dbo].[Your2ndDbTable] WHERE Category = 'Cat')
Could I create function in the database where my EF Core entities are modeled?
You could create function, stored procedure and view to achieve that. Afterwards, you should define that within a POCO Class finally call that on your context. For instance, here I am showing the example using a SQL view:
SQL view:
USE [DatabaseName_Where_You_Want_to_Create_View]
CREATE VIEW [ExecuteQueryFromOneDbToAnother]
AS
SELECT UserId, UserType,CreatedDate
FROM [RentalDb].[dbo].[Users]
WHERE UserId = (SELECT AnimalId
FROM [PetAnalyticsDb].[dbo].[Animal]
WHERE Category = 'Cat')
Note: I am simulating the example where I have two database from that I have two table where these columns, I would use in first database table UserId, UserType, CreatedDate and in second database from Animal table from the AnimalId I will search the user
How would that work code wise?
Following example would guided you how the implementation in the code should be.
Database context:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext (DbContextOptions<ApplicationDbContext > options) : base(options)
{
}
    public DbSet<MultipleDBQueryExecutionModel> multipleDBQueryExecutionModels { get; set; }
            
    override void OnModelCreating(ModelBuilder modelBuilder)
{
        modelBuilder.Entity<MultipleDBQueryExecutionModel>().ToTable("ExecuteQueryFromOneDbToAnother");
    }
}
Note: put your view name while map in DbContext to table ToTable("ExecuteQueryFromOneDbToAnother");. Here ExecuteQueryFromOneDbToAnother is the view name.
POCO class:
public class MultipleDBQueryExecutionModel
{
[Key]
public Int UserId { get; set; }
public string UserType { get; set; }
public DateTime CreatedDate { get; set; }
}
Controller:
[HttpGet]
public ActionResult GetDataFromDifferentDatabase()
{
var data = _context.multipleDBQueryExecutionModels.ToList();
return Ok(data);
}
Output:

Using aliases in stored procedures with JPA entity

I have a Workers table with column name: "WorkerID"
so I have created entity with #Column(name = "WorkerID").
Whenever I try to use stored procedure that selects WorkerID as ID, it doesn't work. It says The column name WorkerID is not valid.
Is there any annotation I can use to make the both parameters WorkerID and ID not to be mandatory? (so I can use this stored procedure and a simple select on workers table)
The exception given upon executing the query:
com.microsoft.sqlserver.jdbc.SQLServerException: The column name worker_id is not valid.
Failed query:
SELECT Worker_ID AS [ID] From Workers
Working query:
SELECT Worker_ID From Workers
The entity:
#PropertySource("classpath:application.properties")
#Entity
#Table(name = "Workers")
#Data
#NoArgsConstructor
#RequiredArgsConstructor
public class Worker {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "Worker_ID")
protected long Worker_ID;
#Column(name = "Email")
private String Email;
#Column(name = "Username")
private String Username;
}
I want to be able to run both queries with the same entity. Is it feasible?
Thanks!

Google App Engine Objectify 5.1.21 - Many-to-many relationship queries

I'm new on Objectify coding and I need your help to solve a problem with Many-to-many relationship query.
I have 2 entities named User and Installation:
#Entity
public class User {
#Id private String login;
private String password;
#Index private String name;
#Index private String firstName;
#Index private byte right;
}
#Entity
public class Installation {
#Id private long id;
#Index private long clientId;
#Index private String name;
private String address1;
private String address2;
#Index private String postCode;
private String city;
#Index private String countryCode;
#Index private int status;
}
A user can access to several installation and an installation can have several users : many-to-many relationship. I want to map these entities but I don't want to load systematically installations when I load users. So, I created an entity for mapping Users and Installations :
#Entity
public class InstallUser {
#Id private Long id;
#Index Key<User> userKey;
#Index Key<Installation> instalKey;
public void setLink(User user, Installation instal){
//initialize
this.userKey = Key.create(User.class, user.getLogin());
this.instalKey = Key.create(Installation.class, instal.getId());
}
}
Could you help me for writing the queries to :
load all installations of a user identified by his login (#id) ;
load all users who have access to an installation identified by its id (#id) ;
load all installations of a user identified by his login (#id) and filtered by his right (right=2 for example).
Thank you in advance for your help.
While the datastore doesn't do joins for you, you can still do joins - you're the query planner. So do what an RDBMS would do. For example, to perform #1 ("load all installations of a user identified by his login") you would:
Make a Key<User> for that user
Find all InstallUsers associated with that user
Use all the relevant Key<Installation>s to batch load the installatons.
You can be slightly more clever by using Ref<?>s instead of Key<?>s in the InstallUser and using the #Load annotation to automatically fetch the Installation.
There are quite a few other ways of structuring this data as well. Depending on the arity of the relationships, you might use a list property in either User or Installation instead of a separate relationship entity. But you're on the right path.

spring data insert if not exists entity with field

Can anyone recommend a way to perform inserts in a database table via spring data jpa (in a clustered environment) only when the entry doesn't already exist in the database?
As an example situation, take a database with message and email_address tables. When a new message addressed to 'user#so.com' is added to the message table, a check will be done in the email_address table whether the email 'user#so.com' exists in the email_address and if it doesn't, it gets added to the database. Afterwards the email address entity field is set on the message entity and subsequently the message entity is saved.
#Entity
public class Message {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private EmailAddress emailAddress;
private String content;
}
#Entity
public class EmailAddress {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
// a unique constraint exists on this field on the database
private String email;
}
What should there be done with the spring data jpa EmailAddressRepository to avoid database exceptions that can occur when concurrently trying to insert entities with the same email address?
You could run a check inside a #PrePersist annotated method in your entity. Other than that, I don't think JPA or spring-data provide something out of the box for that.

Hibernate annotation: one-To-one onDelete action cannot set to CASCADE

I would like to create two table USER and USERDETAIL to fulfill:
USERDETAIL have reference to USER table.
Operation on USER table do not need to aware of USERDEAIL table existence.
This should be one-to-one non bidirectional relationship.
The entity classes:
#Entity
#Table(name="USER")
public class User implements Serializable{
#Id
#Column(name="ID")
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
//...
}
#Entity
#Table(name="USERDETAIL")
public class UserDetail implements Serializable{
#Id
#Column(name="ID")
#GeneratedValue(generator = "gen")
#GenericGenerator(name = "gen", strategy = "foreign",
parameters = #Parameter(name = "property", value = "user"))
private String id;
#OneToOne(optional= false , targetEntity=User.class, cascade= CascadeType.ALL)
#OnDelete(action = OnDeleteAction.CASCADE)
//#JoinColumn(name="foreign_id",referencedColumnName="ID")
#PrimaryKeyJoinColumn
private User user;
//...
}
This create two table correctly and the USERDETAIL have foreign key constraint that its primary key is refernece by USER's id. However, the on Delete action is Restrict but not Cascade. I cannot delete a row of USER because of this.
I am using MySQL Sever 5.1. It does not seem like it does not support on delete action is cascade. Because I can manually delete the constraint and add a new constraint that set to on delete is cascade and work as I expected.
Your code should be:
#Entity
#Table(name="USER")
public class User implements Serializable{
#Id
#Column(name="ID")
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
//...
#OneToOne(cascade = CascadeType.ALL)
#JoinColumn(name="userdetail_id")
public UserDetail getUserDetail() {
...
}
}
#Entity
#Table(name="USERDETAIL")
public class UserDetail implements Serializable{
#Id
#Column(name="ID")
#GeneratedValue(generator = "gen")
#GenericGenerator(name = "gen", strategy = "foreign",
parameters = #Parameter(name = "property", value = "user"))
private String id;
#OneToOne(optional= false , targetEntity=User.class, mappedBy = "userDetail")
#PrimaryKeyJoinColumn
private User user;
//...
}
Basically, I suggest to make it bidirectionaly, with User class is the owner (by using mappedBy in UserDetail class). That way, when you delete a user, user detail will be deleted.
Finally, I have solved the problem.
First of all, I have follow http://www.mkyong.com/hibernate/hibernate-one-to-one-relationship-example-annotation/ to create oneToOne mapping entities.
However, when I start the Tomcat, it always throw NullPointerException on mapping. Therefore, I come up with my question entities and seem to work fine except the deletion.
I finally realize it is just a bug that hibernate-anoatation cause. I then use 3.4.0.ga version and follow the link again. By replace #GeneratedValue(strategy = IDENTITY) (I don't know why using this, hibernate cannot create table) to
#GeneratedValue(generator = "system-uuid")
#GenericGenerator(name = "system-uuid", strategy = "uuid")
it work as I expected.
Although there is no foreign-key constrain on the table, deleting owner (USER) table really can also delete the child (USERDETAIL) table correctly with hibernate handle.
I also do not need to worry about update owner table with no child field on it. The mappedBy side actually has no physical mapping defined as Khue Vu said. Hibernate is smart enough not to delete the relation.

Resources